OOP principle

1. 依赖倒置原则

针对接口类(用纯虚函数提供接口的类)编程,不针对实现类(复写纯虚函数的类)编程。

2. 开-闭原则

open:用户需求增加时,添加新代码
closed: 不改变已写代码

3. 里氏代换原则

任何基类可以出现的地方,子类都可以出现。

4. 接口隔离原则

在接口类中,将复杂接口的各个部分分割成单独的接口,避免实现者多实现他们不需要的功能。

5. 单一责任原则

一个类实现一个任务。

singleton

单件模式,即造一个类,全局访问下只有一个实例。

在类里定义一个自己的静态对象,然后搞一些访问这个对象的接口就行了。

要把拷贝、移动构造函数删了。

class A {
private:
	static A a;
	int i;
	A(int i_) {
		i = i_;
	}
public:
	A(const A&) = delete;
	A(A&&) = delete;
	static A* instance() {return &a;}
	int val() const { return i;}
};
A A :: a{10};

int main() {
	cout << A :: instance() -> val() << endl;
}

暂不知有啥用。

adapater

对象适配器

即 \(A(客户端需求)\leftarrow_{composition} B \leftarrow_{inheritance}C(服务)\)

类适配器

\(A,C\leftarrow_{inheritance} B\)

B同时继承客户端和服务端的所有功能,自己在里面重新复写需求,成为新的客户端。

Simple Factory

如果按正常的想法,搞一个pizza抽象类,客户端的orderpizza(pizzaType)就会违反开-闭原则,每加一种type就要加个if...else。

简单工厂就是把决定哪个pizza的过程独立出来,另写一个工厂类完成。

但工厂类还是不满足开-闭原则。

写的时候简单工厂更像一种编程习惯。

Factory method:

搞一个抽象工厂类,一个具体工厂生产一个产品。

用户端直接确定用哪个工厂,把factory带入orderpizza即可。

说真的没什么质的改变。

Abstract Factory:

如果除了pizza还有burger,burger也有各种口味,口味和pizza有重合。

同样创建burger的抽象类和具体类。

这时让每个工厂都生产对应口味的pizza和Burger即可。

用户端先确定口味工厂,然后再orderpizza或orderburger。

这玩意儿本质就是工厂方法套到二维上。

Observer

OOP课程笔记-2-设计模式_成员函数

暂时用不到,不管了。

Strategy:

考虑一个抽象类D有三个抽象成员函数,每个抽象成员函数都有两种写法,那么要\(2^3=8\)个具体类。

那么搞:
\(A \leftarrow_{inheritance} A1,A2\)
\(B \leftarrow_{inheritance} B1,B2\)
\(C \leftarrow_{inheritance} C1,C2\)

A,B,C里有抽象的本来的成员函数。

\(A,B,C\leftarrow_{composition} D\)

D中搞一些装载A,B,C的具体类的函数,再搞一些调用A,B,C的具体类的函数来代替本来的就行了。

那么D就可以做到三个成员函数任选。

template Method:

基类A搞一堆纯虚函数,以及写完主流程调用这些函数,以及然后搞一堆具体类A1、A2、A3去补充函数。

大作业Wordle用的就是这个方法。

显然Strategy和Template Method可以有机结合。

Proxy