工厂模式
三类:简单工厂模式(Simple Factory),工厂方法模式(Factory Method),抽象工厂模式(Abstract Factory)
定义:简单工厂模式又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
实现:简单工厂
具体情形:有一个肥皂厂,生产各种肥皂,有舒肤佳,夏士莲,娜爱斯等。给这个肥皂厂建模。
UML图如下:
对于简单设计模式的结构图,我们可以很清晰的看到它的组成:
1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。
2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
3) 具体产品角色:工厂类所创建的对象就是此角色的实例。
简单设计模式存在的目的很简单:定义一个用于创建对象的接口。
缺点:
对修改不封闭,新增加产品您要修改工厂。违法了鼎鼎大名的开闭法则(OCP)。
由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
代码实现:
1.#include <iostream>
2.using namespace std;
3.enum PRODUCTTYPE {SFJ,XSL,NAS};
4.class soapBase
5.{
6. public:
7. virtual ~soapBase(){};
8. virtual void show() = 0;
9.};
10.
11.class SFJSoap:public soapBase
12.{
13. public:
14. void show() {cout<<"SFJ Soap!"<<endl;}
15.};
16.
17.class XSLSoap:public soapBase
18.{
19. public:
20. void show() {cout<<"XSL Soap!"<<endl;}
21.};
22.
23.class NASSoap:public soapBase
24.{
25. public:
26. void show() {cout<<"NAS Soap!"<<endl;}
27.};
28.
29.class Factory
30.{
31. public:
32. soapBase * creatSoap(PRODUCTTYPE type)
33. {
34. switch(type)
35. {
36. case SFJ:
37. return new SFJSoap();
38. break;
39. case XSL:
40. return new XSLSoap();
41. break;
42. case NAS:
43. return new NASSoap();
44. break;
45. default:break;
46. }
47.
48. }
49.};
50.
51.int main()
52.{
53. Factory factory;
54. soapBase* pSoap1 = factory.creatSoap(SFJ);
55. pSoap1->show();
56. soapBase* pSoap2 = factory.creatSoap(XSL);
57. pSoap2->show();
58. soapBase* pSoap3 = factory.creatSoap(NAS);
59. pSoap3->show();
60. delete pSoap1;
61. delete pSoap2;
62. delete pSoap3;
63. return 0;
64.}
以下情况下可以使用简单工厂模式:
工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。
工厂模式:
定义:用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
实现:
最近莫名肥皂需求激增!! 于是要独立每个生产线,每个生产线只生产一种肥皂。
UML图如下:
1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
优点:
良好的封装性,代码结构清晰;降低模块的耦合性;扩展优秀;典型的解耦框架,高层模块只需要知道产品的抽象类。
缺点:
由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
以下情况下可以使用工厂方法模式:
一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
代码实现:
1.#include <iostream>
2.using namespace std;
3.enum SOAPTYPE {SFJ,XSL,NAS};
4.
5.class soapBase
6.{
7. public:
8. virtual ~soapBase(){};
9. virtual void show() = 0;
10.};
11.
12.class SFJSoap:public soapBase
13.{
14. public:
15. void show() {cout<<"SFJ Soap!"<<endl;}
16.};
17.
18.class XSLSoap:public soapBase
19.{
20. public:
21. void show() {cout<<"XSL Soap!"<<endl;}
22.};
23.
24.class NASSoap:public soapBase
25.{
26. public:
27. void show() {cout<<"NAS Soap!"<<endl;}
28.};
29.
30.class FactoryBase
31.{
32. public:
33. virtual soapBase * creatSoap() = 0;
34.};
35.
36.class SFJFactory:public FactoryBase
37.{
38. public:
39. soapBase * creatSoap()
40. {
41. return new SFJSoap();
42. }
43.};
44.
45.class XSLFactory:public FactoryBase
46.{
47. public:
48. soapBase * creatSoap()
49. {
50. return new XSLSoap();
51. }
52.};
53.
54.class NASFactory:public FactoryBase
55.{
56. public:
57. soapBase * creatSoap()
58. {
59. return new NASSoap();
60. }
61.};
62.
63.
64.
65.int main()
66.{
67. SFJFactory factory1;
68. soapBase* pSoap1 = factory1.creatSoap();
69. pSoap1->show();
70. XSLFactory factory2;
71. soapBase* pSoap2 = factory2.creatSoap();
72. pSoap2->show();
73. NASFactory factory3;
74. soapBase* pSoap3 = factory3.creatSoap();
75. pSoap3->show();
76. delete pSoap1;
77. delete pSoap2;
78. delete pSoap3;
79. return 0;
80.}
抽象工厂类:
定义:为创建一组相关或相关依赖的对象提供给一个接口,而且无需指定他们的具体类;
实现:
对于上面的结构图,可以看出抽象工厂模式,比前两者更为的复杂和一般性,抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。
抽象工厂模式:给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足一下条件:
1)系统中有多个产品族,而系统一次只可能消费其中一族产品。
2)同属于同一个产品族的产品以其使用。
抽象工厂模式的组成(和工厂方法模式一样):
1)抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
优点:
封装性,产品实现类只要知道工厂类是谁就能创建出一个需要的对象。
产品族内约束非公开。
缺点:产品族扩展难(产品族由2变到3)
使用场景: 跨平台应用
一个对象族(或者没有任何关系的对象)有相同的约束,则可以使用抽象工厂模式
一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
系统中有多于一个的产品族,而每次只使用其中某一产品族。
属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
抽象工厂模式与工厂方法模式的区别
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。我们依然拿生产汽车的例子来说明他们之间的区别。
在上面的类图中,两厢车和三厢车称为两个不同的等级结构;而2.0排量车和2.4排量车则称为两个不同的产品族。再具体一点,2.0排量两厢车和2.4排量两厢车属于同一个等级结构,2.0排量三厢车和2.4排量三厢车属于另一个等级结构;而2.0排量两厢车和2.0排量三厢车属于同一个产品族,2.4排量两厢车和2.4排量三厢车属于另一个产品族。
明白了等级结构和产品族的概念,就理解工厂方法模式和抽象工厂模式的区别了,如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。在本例中,如果一个工厂模式提供2.0排量两厢车和2.4排量两厢车,那么他属于工厂方法模式;如果一个工厂模式是提供2.4排量两厢车和2.4排量三厢车两个产品,那么这个工厂模式就是抽象工厂模式,因为他提供的产品是分属两个不同的等级结构。当然,如果一个工厂提供全部四种车型的产品,因为产品分属两个等级结构,他当然也属于抽象工厂模式了。
代码实现
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Human
{
public :
virtual void getColor() = 0;
virtual void talk() = 0;
virtual void getSex() = 0;
};
class AbstraWhiteHuman : public Human
{
public :
void getColor()
{
cout<<"白色人种的皮肤颜色是白色的"<<endl;
}
void talk()
{
cout<<"说话单字节"<<endl;
}
};
class AbstraBlackHuman : public Human
{
public :
void getColor()
{
cout<<"黑色人种的皮肤颜色是黑色的"<<endl;
}
void talk()
{
cout<<"说话听不懂"<<endl;
}
};
class AbstraYellowHuman : public Human
{
public :
void getColor()
{
cout<<"黄种人种的皮肤颜色是黄色的"<<endl;
}
void talk()
{
cout<<"说话双字节"<<endl;
}
};
class FemaleYellowHuman : public AbstraYellowHuman
{
public:
void getSex()
{
cout<<"黄人女性"<<endl;
}
};
class MaleYellowHuman : public AbstraYellowHuman
{
public:
void getSex()
{
cout<<"黄人男性"<<endl;
}
};
class FemaleBlackHuman : public AbstraBlackHuman
{
public:
void getSex()
{
cout<<"黑人女性"<<endl;
}
};
class MaleBlackHuman : public AbstraBlackHuman
{
public:
void getSex()
{
cout<<"黑人男性"<<endl;
}
};
class FemaleWhiteHuman : public AbstraWhiteHuman
{
public:
void getSex()
{
cout<<"白人女性"<<endl;
}
};
class MaleWhiteHuman : public AbstraWhiteHuman
{
public:
void getSex()
{
cout<<"白人男性"<<endl;
}
};
#if 0
class HumanFactory
{
public:
virtual FemaleYellowHuman createYellowHuman() = 0;
virtual FemaleWhiteHuman createWhiteHuman() = 0;
virtual FemaleBlackHuman createBlackHuman() = 0;
};
#endif
class HumanFactory
{
public:
virtual Human* createYellowHuman() = 0;
virtual Human* createWhiteHuman() = 0;
virtual Human* createBlackHuman() = 0;
};
class FemaleFactory: public HumanFactory
{
public:
Human* createBlackHuman()//java书上是返回Human 但是抽象类不允许返回
{
return new FemaleBlackHuman();//创建临时对象
}
Human* createWhiteHuman()
{
return new FemaleWhiteHuman();
}
Human* createYellowHuman()
{
return new FemaleYellowHuman();
}
};
class MaleFactory: public HumanFactory
{
public:
public:
Human* createBlackHuman()//java书上是返回Human 但是抽象类不允许返回
{
return new MaleBlackHuman();//创建临时对象
}
Human* createWhiteHuman()
{
return new MaleWhiteHuman();
}
Human* createYellowHuman()
{
return new MaleYellowHuman();
}
};
int main()
{
MaleFactory male;
HumanFactory *MaleFactory = &male ;
FemaleFactory female;
HumanFactory *FemaleFactory = ♀
Human *MaleYellowHuman = MaleFactory->createYellowHuman();
Human *FemaleYellowHuman = FemaleFactory->createYellowHuman();
cout<<"生产第一个黄色女性"<<endl;
FemaleYellowHuman->getColor();
FemaleYellowHuman->talk();
FemaleYellowHuman->getSex();
cout<<"生产第一个黄色男性"<<endl;
MaleYellowHuman->getColor();
MaleYellowHuman->talk();
MaleYellowHuman->getSex();
return 0;
}