【设计模式】雷锋依然在人间 --- 工厂方法模式
一,概述
工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题:
首先完全实现‘开-闭 原则’,实现了可扩展。
其次更复杂的层次结构,可以应用于产品结果复杂的场合。
工厂方法模式的对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
工厂方法模式(Factory Method pattern)是最典型的模板方法模式(Templete Method pattern)应用。
二,工厂方法模式角色与结构
抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。在上图中有两个这样的角色:BulbCreator与TubeCreator。 抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在上图中,这个角色是Light。
具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
三,工厂方法模式的应用
工厂方法经常用在以下两种情况中:
第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。
第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实?
四,例子
首先参考简单工厂模式中计算机的例子 简单工厂模式
接下来的例子是对简单工厂模式的升级 工厂方法模式
对比:
简单工厂模式,要添加内容,需要更改源代码,不符合开放 - 封闭原则。
工厂方法模式,只需要增加子类,而不需要更改方法。
#include <iostream> class Operation//操作抽象类 { public: Operation():m_numberA(0),m_numberB(0) //初始化两个参数为0 { }; Operation(double numberA, double numberB):m_numberA(numberA),m_numberB(m_numberB) { }; double getA() { return m_numberA; }; void setA(double number) { m_numberA = number; }; double getB() { return m_numberB; }; void setB(double number) { m_numberB = number; }; virtual double GetResult() //返回两个操作数 操作后的结果 { return 0; } protected: double m_numberA; double m_numberB; }; class OperationAdd :public Operation //具体操作子类 { public: double GetResult() { double result = 0; result = m_numberA + m_numberB; return result; } }; class OperationSub :public Operation { public: double GetResult() { double result = 0; result = m_numberA - m_numberB; return result; } }; class OperationMul :public Operation { public: double GetResult() { double result = 0; result = m_numberA * m_numberB; return result; } }; class OperationDiv :public Operation { public: double GetResult() { double result = 0; if ( m_numberB == 0 ) throw "被除数不能为零"; result = m_numberA / m_numberB; return result; } }; class IFactory //接口 { public: virtual Operation* CreateOperation(void) = 0; }; //加法工厂 class AddFactory :public IFactory { public: Operation* CreateOperation(void) { return new OperationAdd(); }; }; //减法工厂 class SubFactory :public IFactory { public: Operation* CreateOperation(void) { return new OperationSub(); }; }; //乘法工厂 class MulFactory :public IFactory { public: Operation* CreateOperation(void) { return new OperationMul(); }; }; //除法工厂 class DivFactory :public IFactory { public: Operation* CreateOperation(void) { return new OperationDiv(); }; }; int main() { IFactory* operFactory = new AddFactory(); Operation* oper = operFactory->CreateOperation(); oper->setA(1); oper->setB(2); double result = oper->GetResult(); std::cout<<"result:"<<result<<"\n"; delete operFactory; delete oper; return 0; }
五,学雷锋案例
1)菜鸟一
#include <iostream> using namespace std; class leiFeng { public: void Sweep() { cout<<"扫地"<<endl; } void Wash() { cout<<"洗衣"<<endl; } void BuyRice() { cout<<"买米"<<endl; } }; class UnderGraduateStudent : public leiFeng { }; int main() { leiFeng *xueleifeng = new UnderGraduateStudent(); xueleifeng->Sweep(); xueleifeng->Wash(); xueleifeng->BuyRice(); delete xueleifeng ; return 0; }
2)简单工厂实现
缺点:如果想增加产品,需要更改 simpleFactory 类。这不符合开放--封闭原则
#include <iostream> using namespace std; class leiFeng { public: void Sweep() { cout<<"扫地"<<endl; } void Wash() { cout<<"洗衣"<<endl; } void BuyRice() { cout<<"买米"<<endl; } }; class UnderGraduateStudent : public leiFeng { }; class Volunteer : public leiFeng { }; class SimpleFactory { public: static leiFeng* CreateLeiFeng(string type) { leiFeng *result; if(type == "学习雷锋的大学生") result = new UnderGraduateStudent(); else if(type == "社区志愿者") result =new Volunteer(); return result; } }; int main() { SimpleFactory sfactory; leiFeng *xueleifeng = sfactory.CreateLeiFeng("社区志愿者"); xueleifeng->Sweep(); xueleifeng->Wash(); xueleifeng->BuyRice(); delete xueleifeng; return 0; }
3)工厂方法模式实现
缺点:每增加一个产品,需要增加产品工厂的类。增加了代码量
优点:如果要增加类,不需要更改任何类,只需要添加代码。
#include <iostream> using namespace std; class leiFeng { public: void Sweep() { cout<<"扫地"<<endl; } void Wash() { cout<<"洗衣"<<endl; } void BuyRice() { cout<<"买米"<<endl; } }; class UnderGraduateStudent : public leiFeng { }; class Volunteer : public leiFeng { }; class IFactory //接口抽象类 { public: virtual leiFeng* CreateLeiFeng()=0; }; class UnderGraduateFactory : public IFactory { public: leiFeng* CreateLeiFeng() { return new UnderGraduateStudent(); } }; class VolunteerFactory : public IFactory { public: leiFeng* CreateLeiFeng() { return new Volunteer(); } }; int main() { IFactory *factory = new UnderGraduateFactory(); leiFeng *student= factory->CreateLeiFeng(); student->Sweep(); student->Wash(); student->BuyRice(); delete student; return 0; }