GoF 23
23 种设计模式:一种思维,一种态度,一种进步
OOP 七大设计原则
- 开闭原则:对扩展开放,对修改关闭
- 里氏替换原则:继承必须确保父类所拥有的性质在子类仍然成立
- 依赖倒置原则:要面向接口编程,不要面向实现编程
- 单一职责原则:控制类的粒度大小,将对象解耦、提高其内聚性
- 接口隔离原则:要为各个类建立他们需要的专用接口
- 递米特法则:只与你的直接朋友交谈,不跟陌生人说话,降低耦合度
- 合成复用原则:尽量先使用组合或者聚合等关联关系实现,其次才考虑继承
工厂模式
作用:实现了创建者和调用者的分离
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
核心本质:
- 实例化对象不使用 new ,用工厂方法代替
- 将选择实现类,创建对象统一管理和控制,从而将调用者和我们的实现类解耦合
简单工厂案例代码
抽象的汽车类
class Car{
public:
virtual void name() = 0;
//汽车特性
int color; //颜色
double price; //价格
};
实现大众车
class DZ :public Car{
public:
virtual void name(){
cout<<"大众车"<<endl;
}
};
实现宝马车
class BMW:public Car{
public:
virtual void name(){
cout<<"宝马"<<endl;
}
};
实现车工厂
class CarFactory{
public:
Car getCar(string car){
if(car == "DZ"){
return new DZ();
}
else if(car == "BMW"){
return new BMW();
}
else{
return nullptr;
}
}
};
消费者买车
{
// 普通买车
Car car = new DZ();
Car car2 = new BMW();
car.name();
car2.name();
//简单工厂
Car car1 = CarFactory.getCar("BMW"); // 传参数
Car car2 = CarFactory.GetCar("DZ");
}
弊端:对于简单工厂模式,通过接收不同的参数创建不同的对象,虽然绕开 new 的创建方式,但是还有没满足开闭原则
所以可以采用工厂方法模式
注意:在大多数实际业务情况下,我们用的还是简单工厂,如果使用工厂方法反而显得复杂
工厂方法模式案例
车工厂
class CarFactory{
public:
virtual Car GetCar() = 0;
};
大众车的对象创建
class DZFactory:public CarFactory{
public:
virtual Car getCar(){
return new DZ();
}
};
宝马车的对象创建
class BMWFactory:public CarFactory{
public:
virtual Car GetCar(){
return ner BMW();
}
};
客户端买车
{
Car car1 = new WMFactory.GetCar();
Car car2 = new BMWFactory.GetCar();
car1.name();
car2.name();
}
这样就不需要改变原有的类,只要有新的车类型,直接扩展
抽象工厂模式
提供了一个创建一系列相关的或者相互依赖对象的关系,无需指定他们具体的类
手机抽象类
class Iphone{
public:
virtual void open()=0;
virtual void shotdown()= 0;
virtual void callup() = 0;
virtual void sendMessage() = 0;
};
路由器抽象类
class Route{
public:
virtual void open()=0;
virtual void showdown()=0;
virtual void openwifi()=0;
virtual void setting()=0;
};
手机的具体实现
1、小米手机
class XiaomiIphone:public Iphone{
public:
void open(){
cout<<"小米手机开机"<<endl;
}
void showdown(){
cout<<"小米手机关机"<<endl;
}
//...
};
2、华为手机
class HuaweiIphone:public Iphone{
public:
void open(){
cout<<"华为手机开机"<<endl;
}
void shotdown(){
cout<<"华为手机关机"<<endl;
}
//...
};
3、…
路由器的具体实现
1、小米路由器
class XiaomiRoute:public Route{
public:
void open(){
cout<<"小米路由器打开"<<endl;
}
//...
};
2、华为路由器
class HuaweiRoute:public Route{
public:
void open(){
cout<<"华为路由器打开"<<endl;
}
//...
}
3、…
生产产品抽象工厂
class IproductFactory{
public:
//生产手机
virtual Iphone iphoneProduct() = 0;
//生产路由器
virtual Route RouteProduct() = 0;
};
小米具体工厂
class XiaomiFactory:public IprductFactory{
public:
Iphone iphoneProduct(){
return new XiaomiIphone();
}
Route RouteProduct(){
return new XiaomiRoute();
}
};
华为具体工厂
class HuaweiFactory:public IprductFactory{
public:
Iphone iphoneProduct(){
return new HuaweiIphone();
}
Route RouteProduct(){
return new HuaweiRoute();
}
};
客户端
{
cout<<"小米"<<endl;
// 通过抽象工厂拿到小米工厂的对象
XiaomiFactory xiaomifactory = new XiaomiFactory();
// 通过小米工厂对象产出小米手机和小米路由器
Iphone iphone = xiaomifactory.iphone();
Route route = xiaomifactory.route();
// 小米手机实现打电话
iphone.callup();
//...
}
使用场景
- 客户端不依赖产品实例如何被创建,实现细节等,比如你只管用手机打电话就行了,管它是怎么实现的
- 强调一系列相关的产品对象,比如小米手机,华为手机,苹果手机,都属于手机
- 提供一个产品类库,所有的产品以同样的接口出现,比如手机都可以打电话,发短信等功能
优点:
具体产品在应用层代码隔离,无需关系实现细节
将一系列的产品统一到一起创建,不再是创建一个产品,设计一个工厂了
缺点:
规定了所有可能被创建的产品集合
系统更加抽象,难理解
红框框的部分是稳定抽象的,其他是具体变化的
具体依赖稳定的,而不依赖细节