工厂方法模式
1.1 分类
(类)创建型
1.2 提出问题
一个物流公司最初只使用卡车运输,现需要增加轮船运输业务。目前的程序代码与卡车关联。
1.3 解决方案
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
1.4 实现关键
如何把new关起来,实现创造者和产品松耦合?
- 产品(Product)将会对接口进行声明。
- 具体产品(Concrete Products)是产品接口的不同实现。
- 创建者(Creator)声明返回产品对象的工厂方法。
- 具体创建者(Concrete Creators) 将会重写基础工厂方法, 使其返回不同类型的产品。
1.5 示例代码
#include <iostream>
//产品的接口
class Transport {
public:
virtual ~Transport(){}
virtual void deliver() const = 0;
};
//产品A
class Truck:public Transport {
public:
void deliver() const override{
std::cout << "卡车运输货物中ing。\n";
}
};
//产品B
class Ship :public Transport {
public:
void deliver() const override {
std::cout << "轮船运输货物中ing。\n";
}
};
//创造者(注意:除了创建产品以外,创造者还有自己的业务需要处理)
class Logistics {
public:
virtual ~Logistics(){}
//工厂方法的核心
virtual Transport * factoryMethod() const = 0;
void doSomething() const {
Transport * transport= factoryMethod();
transport->deliver();
delete transport;
}
};
//具体的创造者A
class TruckLogistis:public Logistics {
public:
virtual ~TruckLogistis(){}
virtual Transport* factoryMethod() const override{
return new Truck();
}
};
//具体的创造者B
class ShipLogistis :public Logistics {
public:
virtual ~ShipLogistis() {}
virtual Transport* factoryMethod() const override {
return new Ship();
}
};
int main()
{
Logistics* truckLogistics = new TruckLogistis();
Logistics* shipLogistics = new ShipLogistis();
truckLogistics->doSomething();
truckLogistics->doSomething();
shipLogistics->doSomething();
shipLogistics->doSomething();
shipLogistics->doSomething();
delete truckLogistics;
delete shipLogistics;
}
1.6 举个栗子
跨平台的对话框:在不同的操作系统下,UI组件外观或许略有不同,但其功能保持一致。Windows系统中的按钮在Linux系统中仍然是按钮。 如果使用工厂方法,就不需要为每种操作系统重写对话框逻辑。
1.7 总结
- 对扩展开放,对修改关闭。
- 依赖倒置,避免依赖具体的类,尽量依赖抽象。可以避免创建者和具体产品之间的紧密耦合。
- 单一职责原则。将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。
- 和针对接口编程,不要针对实现编程相比,依赖倒置,更注重抽象。产品和创造者都要依赖抽象。而倒置指的是从具体的产品,往上依赖。
- 缺点:应用工厂方法模式需要引入许多新的子类,代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。