今天我学习了一下简单工厂模式,其实简单工厂模式并不被包含于GoF 23种设计模式中,但也是会被频繁的使用在开发中,而且也算是其它工厂模式学习的入门吧。
首先,我想通过一个例子,引入今天的主题。如果我要设计一个学校职工信息管理系统,我要向服务器请求老师、学生、和其他工作人员的基本信息,那我们应该会如何进行设计呢?在不了解各种面向对象设计模式的时候,我们很容易想到的一种方法就是,先定义三个类分别是Student类、Teacher类、Other类,这三个类中分别存放了不同的对应相应类的属性。然后定义一个People类用来继承前面定义的三个类,并在其中加入一个classType来帮助返回我要请求的类中的数据。于是我们很容易写出了如下代码:
class People: public Student,public Teacher,public Other { private: string type; public: People(string myType) { this->type = myType; switch(this->type) { case "Student":{ //初始化学生信息 }break; case "Teacher":{ //初始化教师信息 }break; case "Other":{ //初始化其他员工信息 }break; default:break; } } void display() { if(this->type == "Student") { //输出学生信息 } else if(this->type == "Teacher") { //输出教师信息 } else if(this->type == "Other") { //输出其他员工信息 } } }
1、People类的职责太重了,同时要完成所有的初始化和打印两方面功能,违反了单一职责原则。
2、如果我今后要扩充功能,加入行政人员的资料查询,那么我还将要重新修改代码,将类中的if/else判断再加上一句,增加了添加模块的难度,违反了开闭原则。
3、客户只能用new关键字来创建对象,类和客户端的耦合程度太高。
OK!那就上面三点,我们可以使用简单工厂模式进行怎样的改进呢?
首先,我们要了解,简单工厂模式中的三个角色:
(1)工厂角色:这是该模式的核心部分,负责创建所有产品(对象),同时工厂可以被外界直接调用,创建所需产品的对象。
(2)抽象产品角色:工厂类所创建所有产品(对象)的父类,封装了所有产品的公有方法,用于提高系统的灵活性。
(3)具体产品角色:该模式的创建目标,由他创建对象都是某个具体类的实例(ps:结合上面的例子,就可以理解为Student类、Teacher类、Other类,他们都包含自己特有的属性)
那么,接下来我们就要开始实现了!!
第一步是抽象产品角色,我们要实现的功能是打印功能,因此,我们就需要一个只有display()功能的类,记住要是一个虚基类,因为作为一个接口类,我不需要在类中实现功能。
第二步要开始写我们的具体产品角色了,每个类中的属性有所不同,但是要记住的是:一定要公有继承,抽象产品类,并在自己类中写display()函数。
第三步,也是最重要的一步,我们要在工厂类中,做出逻辑判断,写一个静态函数,通过传进的参数来判断是要请求哪种产品(即Student\Teacher\Other)的参数。
下面给出我写的一个模板的代码(我并没有实现我之前举得例子,因为我学的时候,并没有用这个例子写代码)
/* * class.h * * Created on: 2014-3-20 * Author: linux */ #ifndef CLASS_H_ #define CLASS_H_ #include <iostream> class DisplayInterface { public: virtual void Display(){ }; }; class ClassA :public DisplayInterface { public: ClassA(){ std::cout<<"create class A"<<std::endl; } ~ClassA(){ } virtual void Display(); }; class ClassB :public DisplayInterface { public: ClassB(){ std::cout<<"create class B"<<std::endl; } ~ClassB(){ } virtual void Display(); }; class ClassC :public DisplayInterface { public: ClassC(){ std::cout<<"create class C"<<std::endl; } ~ClassC(){ } virtual void Display(); }; void ClassA::Display(){ std::cout<<"display class A"<<std::endl; } void ClassB::Display(){ std::cout<<"display class B"<<std::endl; } void ClassC::Display(){ std::cout<<"display class C"<<std::endl; } class SimpleFactory { public: static DisplayInterface* getClass(int type) { DisplayInterface* classPtr = nullptr; switch(type) { case 1:classPtr = new ClassA;break; case 2:classPtr = new ClassB;break; case 3:classPtr = new ClassC;break; } return classPtr; } }; #endif /* CLASS_H_ */
#include <iostream> #include "class.h" using namespace std; int main() { DisplayInterface* ptr = SimpleFactory::getClass(1); ptr->Display(); ptr = SimpleFactory::getClass(2); ptr->Display(); ptr = SimpleFactory::getClass(3); ptr->Display(); }
当然简单工厂模式还是可以简化的,就是将抽象产品角色和工厂合并带一个类中。这个读者自己可以尝试一下。
最后介绍的是适用场景:
1、工厂类创建的对象比较少,以免工厂类太过于繁琐
2、客户端只需要知道往工厂传入参数,而并不需要关心对象时如何创建的。