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
暂时用不到,不管了。
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