简单工厂、多态工厂和抽象工厂设计模式的比较

工厂模式的主要作用就是封装对象的创建过程,使得程序员不必准确指定创建对象所需要的构造函数,这样做的一个好处就是增加了程序的可扩展性。由于每个面向对象应用程序的设计都需要创建对象,并且由于人们可能需要通过增加新的类型来扩展应用程序,工厂模式可能是最有用的设计模式之一。

总的来说,工厂模式主要分为三种类型:简单工厂模式、多态工厂模式、抽象工厂模式。这三种模式都属于设计模式中的创建行模式,他们多多少少在设计上有些相似之处,其最终的目的都是为了将对象的实例化部分取出来,进而优化系统的架构,增加程序的可扩展性,下面就这三种模式作对比。

  • 简单工厂模式 

     正如这种模式的名字一样,简单的工厂模式只适用于相对较简单的业务情况下,主要用于小型或者后期需要扩展比较少的项目中。其由三种角色所组成:

  1. 抽象产品角色:主要是提供产品公用的接口,在C++中一般是由抽象类所组成(C++中不存在关键字interface);
  2. 具体产品角色:继承自抽象产品角色,主要是定义各个具体产品的规范,工厂类所创建的对象也是该角色的实例;
  3. 工厂角色:这是简单工厂模式的核心角色,一般含有一定的逻辑判断,根据不同的逻辑判断结果创造不同的产品;

其类图可以简单表示如下:

下面以简单的类子说明这种设计模式。

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4
 5 //抽象产品角色,用于定义产品的接口规范
 6 class Shape{
 7 public:
 8     virtual void draw() = 0;
 9     virtual void erase() = 0;
10     virtual ~Shape();
11 };
12 //具体产品类用于定义各自产品的规范
13 class Circle:public Shape{
14     friend class ShapeFactory;
15 private:
16     Circle();
17 public:
18     void draw();
19     void erase();
20     ~Circle();
21 };
22
23 class Square:public Shape{
24     friend class ShapeFactory;
25 private:
26     Square();
27 public:
28     void draw();
29     void erase();
30     ~Square();
31 };
32
33 class ShapeFactory{
34 public:
35     static Shape* creatshape(string);
36 };
37
38 Shape::~Shape(){ cout << "Shaper::~Shape()" << endl; }
39
40 Circle::Circle(){}
41
42 void Circle::draw(){
43     cout << "Circle::draw()" << endl;
44 }
45
46 void Circle::erase(){
47     cout << "Circle::erase()" << endl;
48 }
49
50 Circle::~Circle(){
51     cout << "Circle::~Circle()" << endl;
52 }
53
54 Square::Square(){}
55
56 void Square::draw(){
57     cout << "Square::draw()" << endl;
58 }
59 void Square::erase(){
60     cout << "Square::erase()" << endl;
61 }
62 Square::~Square(){
63     cout << "Square::~Square()" << endl;
64 }
65
66 Shape* ShapeFactory::creatshape(string id){
67     if ("Circle" == id)
68         return new Circle;
69     else if ("Square" == id)
70         return new Square;
71     else
72         return nullptr;
73 }
74
75 int main()
76 {
77     string _circle("Circle");
78     string _square("Square");
79
80     Shape* ptr = ShapeFactory::creatshape(_circle);
81     ptr->draw();
82     ptr->erase();
83
84     ptr = ShapeFactory::creatshape(_square);
85     ptr->draw();
86     ptr->erase();
87
88     delete ptr;
89 }

其输出结果如下:

  以上就是简单工厂模式了,这有什么好处呢?首先,将具体产品的构造函数声明为private属性,保证了不能直接构造函数的对象(这也是C++中创建单例模式的管用手段),也就是说隐藏了该对象的构建方式。通过将工厂类声明为具体的产品类的友元,保证了工厂类中可以调用具体产品类的构造函数,从而创建对象。客户程序员不需要使用具体的构造函数,所有对象的构造统一由工厂中的静态方法所执行。但是其缺点在于,如果堆shape增加新的具体的产品类,则需要不断的修改工厂模式中的条件判断语句。当产品的种类很少的时候这还是可以接受的,但是如果产品的种类很多,那么工厂类的静态方法中就会存在许多的条件分支。这也就是说简单工厂模式只适用于较小项目或者后期不需要扩展的项目中。

  • 多态工厂模式 

  上面说明了简单工厂模式的具体组成及其优缺点,由于增加新的具体产品的时候,每次都需要修改工厂函数的实现,显然扩展性不是很好。而“四人帮”之所以强调工厂模式的理由则是,该模式可以使不同类型的工厂派生自基本类型的工厂。简单工厂模式其实是多态工厂模式的一个特例。那么多态工厂模式的组成部分有哪些呢?

  1. 抽象工厂角色:这是多态工厂方法的核心,该角色与具体的应用程序无关,是具体工厂角色所必须要继承的接口规范。在C++中一般是由抽象基类所组成;
  2. 具体工厂角色:含有和具体的业务逻辑有关的代码,由应用程序调用以创建具体的产品角色;
  3. 抽象产品角色:作为具体产品所必须遵守的接口规范和继承的基类;
  4. 具体产品角色:具体工厂角色所创建的就是该对象的实例;

该模式下所对应的UML图的类图如下:

下面还是用Shape的类子说明多态工厂模式的运行方式:

 1 #include<iostream>
 2 using namespace std;
 3
 4 //抽象产品角色,用于定义产品的接口规范
 5
 6 class Shape{
 7 public:
 8     Shape(){ cout << "Shape::Shape()" << endl; }
 9     virtual void draw() = 0;
10     virtual void erase() = 0;
11     virtual ~Shape(){ cout << "Shape::~Shape()" << endl; }
12 };
13
14
15 //抽象工厂方法
16 class ShapeFactory{
17 public:
18     ShapeFactory(){ cout << "ShapeFactory::ShapeFactory()" << endl; }
19     virtual ~ShapeFactory(){ cout << "ShapeFactory::~ShapeFactory()" << endl; }
20     virtual Shape* create() = 0;
21 };
22
23 //具体产品类用于定义各自产品的规范
24 class Circle :public Shape{
25     friend class CircleFactory;
26 private:
27     Circle(){ cout << "Circle::Circle()" << endl; }
28 public:
29     void draw(){
30         cout << "Circle::draw()" << endl;
31     }
32     void erase(){
33         cout << "Circle::erase()" << endl;
34     }
35     ~Circle(){
36         cout << "Circle::~Circle()" << endl;
37     }
38 };
39
40 class Square :public Shape{
41     friend class SquareFactory;
42 private:
43     Square(){ cout << "Square::Square()" << endl; }
44 public:
45     void draw(){
46         cout << "Square::draw()" << endl;
47     }
48     void erase(){
49         cout << "Square::erase()" << endl;
50     }
51     ~Square(){
52         cout << "Square::~Square()" << endl;
53     }
54 };
55
56 class CircleFactory:public ShapeFactory{
57 public:
58     CircleFactory(){ cout << "Circlefactory::CircleFactory()" << endl; }
59     Shape* create(){
60         return new Circle;
61     }
62     ~CircleFactory(){ cout << "Circlefactory::~CircleFactory()" << endl; }
63 };
64
65 class SquareFactory :public ShapeFactory{
66 public:
67     SquareFactory(){ cout << "SquareFactory::~SquareFactory()" << endl; }
68     Shape* create(){
69         return new Square;
70     }
71     ~SquareFactory(){ cout << "SquareFactory::~SquareFactory()" << endl; }
72 };
73
74 int main()
75 {
76     Shape* Circleptr = CircleFactory().create();
77     Shape* Squareptr = SquareFactory().create();
78
79     Circleptr->draw();
80     Circleptr->erase();
81
82     Squareptr->draw();
83     Squareptr->erase();
84
85     delete Circleptr;
86     delete Squareptr;
87
88 }

其运行结果如下:

上述工厂方法中,每次增加新的类的时候只要增加新的产品类并增加其对应的工厂函数,然后重新编译运行即可。但是为了能够使工厂类的派生类从其基类中解耦,我们可以使用另一扩展方法,在这种方法中并不需要为每一个类生成一个对应的工厂的派生类,只需要基本的工厂函数维护一个包含类的类型以及与其创建所关联的函数的映射即可(如map容器)。可以通过增加几个新的函数用来注册和注销新的派生类,在运行的时候能注册新的类允许这种类型的工厂模式创建可扩展的接口。

在扩展的方式中不再需要为每个新的产品类增加一个新的工厂类,当增加新的产品类的时候,只需要实现产品的实现类并且将该产品类得创建函数注册到工厂类的map容器中即可。另一个需要注意的是工厂的对象必须保存对象,即最好只有一个工厂对象。这也是工厂对象通常是单件的原因。为了程序的简单明了,这里使用静态变量。废话少说,上代码:

  1 #include<iostream>
  2 #include<string>
  3 #include<map>
  4 using namespace std;
  5
  6 //抽象产品角色,用于定义产品的接口规范
  7
  8 class Shape{
  9 public:
 10     Shape(){ cout << "Shape::Shape()" << endl; }
 11     virtual void draw() = 0;
 12     virtual void erase() = 0;
 13     virtual ~Shape(){ cout << "Shape::~Shape()" << endl; }
 14 };
 15
 16
 17 //抽象工厂方法
 18 class ShapeFactory{
 19 public:
 20
 21     typedef Shape* (*create)();
 22
 23     ShapeFactory(){ cout << "ShapeFactory::ShapeFactory()" << endl; }
 24     virtual ~ShapeFactory(){ cout << "ShapeFactory::~ShapeFactory()" << endl; }
 25
 26     static void Register(const string& str, create ptr){
 27         createmap[str] = ptr;
 28         cout << "ShapeFactory::Register()" << endl;
 29     }
 30     static void Unregister(const string& str){
 31         createmap.erase(str);
 32         cout << "ShapeFactory::Unregister()" << endl;
 33     }
 34     static Shape* CreateShape(const string& str){
 35         cout << "ShapeFactory::CreateShape()" << endl;
 36         map<string, create>::iterator iter = createmap.find(str);
 37         if (iter != createmap.end())
 38             return (iter->second)();
 39         return nullptr;
 40     }
 41 private:
 42     static map<string, create> createmap;
 43 };
 44
 45 //具体产品类用于定义各自产品的规范
 46 class Circle :public Shape{
 47 private:
 48     Circle(){ cout << "Circle::Circle()" << endl; }
 49 public:
 50     void draw(){
 51         cout << "Circle::draw()" << endl;
 52     }
 53     void erase(){
 54         cout << "Circle::erase()" << endl;
 55     }
 56     ~Circle(){
 57         cout << "Circle::~Circle()" << endl;
 58     }
 59     static Shape* create(){
 60         cout << "Circle::create()" << endl;
 61         return new Circle;
 62     }
 63 };
 64
 65 class Square :public Shape{
 66 private:
 67     Square(){ cout << "Square::Square()" << endl; }
 68 public:
 69     void draw(){
 70         cout << "Square::draw()" << endl;
 71     }
 72     void erase(){
 73         cout << "Square::erase()" << endl;
 74     }
 75     ~Square(){
 76         cout << "Square::~Square()" << endl;
 77     }
 78     static Shape* create(){
 79         cout << "Square::create()" << endl;
 80         return new Square;
 81     }
 82 };
 83
 84 map<string, ShapeFactory::create> ShapeFactory::createmap;
 85 int main()
 86 {
 87     ShapeFactory::Register("Circle",Circle::create);
 88     ShapeFactory::Register("Square", Square::create);
 89
 90     Shape* ptr=ShapeFactory::CreateShape("Circle");
 91
 92     ptr->draw();
 93     ptr->erase();
 94
 95     //ShapeFactory::Unregister("Square");如果加上这句则会造成抛出异常,造成程序终止
 96     ptr = ShapeFactory::CreateShape("Square");
 97     ptr->draw();
 98     ptr->erase();
 99
100     delete ptr;
101 }

其运行结果如下:

  • 抽象工厂模式

抽象工厂模式看起来和前面的工厂方法类似,只是它使用若干的工厂方法模式。每个工厂方法模式创建一个不同类型的对象。当创建一个工厂对象的时候,要决定将如何使用由那个工厂创建的所有对象。其组成部分为:

  1. 抽象工厂角色:这是多态工厂方法的核心,该角色与具体的应用程序无关,是具体工厂角色所必须要继承的接口规范。在C++中一般是由抽象基类所组成;
  2. 具体工厂角色:含有和具体的业务逻辑有关的代码,由应用程序调用以创建具体的产品角色;
  3. 抽象产品角色:作为具体产品所必须遵守的接口规范和继承的基类;
  4. 具体产品角色:具体工厂角色所创建的就是该对象的实例;

其类图为:

下面是用一个类子说明抽象工厂模式。代码如下:

 1 #include<iostream>
 2
 3 using namespace std;
 4
 5 class Obstacle{
 6 public:
 7     virtual void action() = 0;
 8 };
 9
10 class Player{
11 public:
12     virtual void interactWith(Obstacle*) = 0;
13 };
14
15 class Kitty :public Player{
16     virtual void interactWith(Obstacle* ob){
17         cout << "Kitty has encountered a ";
18         ob->action();
19     }
20 };
21
22 class Amy :public Player{
23     virtual void interactWith(Obstacle* ob)
24     {
25         cout << "Amy has encountered a ";
26         ob->action();
27     }
28 };
29
30 class Puzzle :public Obstacle{
31 public:
32     void action()
33     {
34         cout << "Puzzle" << endl;
35     }
36 };
37
38 class NastyWeapon :public Obstacle{
39 public:
40     void action()
41     {
42         cout << "NastyWeapon" << endl;
43     }
44 };
45
46 class GameElementFactory{
47 public:
48     virtual Player* makePlayer() = 0;
49     virtual Obstacle* makeObstacle() = 0;
50 };
51
52 class KittyandPuzzle :public GameElementFactory{
53 public:
54     Player* makePlayer(){
55         return new Kitty;
56     }
57     Obstacle* makeObstacle(){
58         return new Puzzle;
59     }
60
61 };
62
63 class KillandDismember :public GameElementFactory{
64 public:
65     Player* makePlayer(){
66         return new Amy;
67     }
68     Obstacle* makeObstacle(){
69         return new NastyWeapon;
70     }
71
72 };
73
74 class GameEnvironment{
75     GameElementFactory* gef;
76     Player* p;
77     Obstacle* ob;
78 public:
79     GameEnvironment(GameElementFactory* factory) :gef(factory), p(factory->makePlayer()), ob(factory->makeObstacle()){}
80     void play(){
81         p->interactWith(ob);
82     }
83     ~GameEnvironment()
84     {
85         delete p;
86         delete ob;;
87         delete gef;
88     }
89 };
90
91
92 int main(){
93     GameEnvironment g1(new KittyandPuzzle), g2(new KillandDismember);
94     g1.play();
95     g2.play();
96 }

其运行结果如下:

抽象工厂模式一般是适用于多个产品族,所谓的产品族是指位于不同产品等级结构中,功能相关联的产品组成的家族。它和多态方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。
而且使用抽象工厂模式还要满足一下条件:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品以其使用。

总结:

工厂模式可以极大地提高程序的可扩展性 ,根据程序的具体特点选择合适的工厂模式有助于后期 程序的扩展和维护!

时间: 2024-10-23 10:20:32

简单工厂、多态工厂和抽象工厂设计模式的比较的相关文章

设计模式之_简单工厂模式、工厂方法模式、抽象工厂模式 、策略模式、策略与工厂的区别(转)

一.前言 话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰).Bmw(宝马).Audi(奥迪)),还雇了司机为他开车.不过,爆发户坐车时总是这样:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上 Audi后他说“开奥迪车!”.你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的 幸运的是这种有病的现象在OO语言中可以避免了.下面以Java语言为基础来引入我们本文的主题:工厂模式! 二.简介

简单工厂模式,工厂方法模式,抽象工厂模式

简单工厂模式.抽象工厂模式.工厂方法模式,这三种工厂模式都属于设计模式中的创建型模式,它们在形式和特点上也多少有些相似,其最终目的都是帮我们将对象的实例化部分取出来,进而优化系统架构,增强系统的扩展性,也就是说更好的体现开放封闭原则. 简单工厂模式: 概念: 简单工厂模式是类的创建模式,又叫做静态工厂方法模式,是由一个工厂类根据传入的参量决定创建出哪一种产品类的实例,涉及到工厂角色.抽象产品角色以及具体产品角色. 结构图: 分析: 一: 简单工厂类是整个模式的关键所在,包含了必要的逻辑判断,根据

工厂模式:简单工厂模式、工厂方法模式和抽象工厂模式

我们一般制造对象时,采用操作符new来进行创建.但是慢慢我们了解到实例化这个活动不应该总是公开地进行,同时初始化还经常造成"耦合"的问题. 如果我们不希望出现上述问题,那么我们就有必要认识一下"工厂模式",它将有助于我们从复杂的依赖中解脱出来. 1)为什么说"new"不好? 当看到"new",就会想到"具体". 我们不应该总是针对实现编程,但是当我们每次使用new时,正是在针对实现编程而不是接口,这很不符合

PHP简单工厂模式、工厂方法模式和抽象工厂模式比较

PHP工厂模式概念:工厂模式是一种类,它具有为您创建对象的某些方法.您可以使用工厂类创建对象,而不直接使用 new.这样,如果您想要更改所创建的对象类型,只需更改该工厂即可.使用该工厂的所有代码会自动更改. 根据抽象程度不同,PHP工厂模式分为:简单工厂模式.工厂方法模式和抽象工厂模式 简单工厂模式: /******代码在原文还是git上都有osgit地址 https://git.oschina.net/mjw/pattern.git  *******/ /** *简单工厂模式与工厂方法模式比较

PHP简单工厂模式、工厂方法模式和抽象工厂模式

PHP工厂模式概念:工厂模式是一种类,它具有为您创建对象的某些方法.您可以使用工厂类创建对象,而不直接使用 new.这样,如果您想要更改所创建的对象类型,只需更改该工厂即可.使用该工厂的所有代码会自动更改.根据抽象程度不同,PHP工厂模式分为:简单工厂模式.工厂方法模式和抽象工厂模式 简单工厂模式: /** *简单工厂模式与工厂方法模式比较. *简单工厂又叫静态工厂方法模式,这样理解可以确定,简单工厂模式是通过一个静态方法创建对象的. */ interface people { function

简单工厂、工厂方法模式、抽象工厂模式

只为每天积累一点点... 简单工厂.工厂方法模式.抽象工厂模式的简单原理. 一.引子 话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰).Bmw(宝马).Audi(奥迪)),还雇了司机为他开车.不过,爆发户坐车时总是这样:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上 Audi后他说“开奥迪车!”.你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!幸运的是这种有病的现象在OO语言中可

Java设计模式-工厂方法模式和抽象工厂模式

工厂方法模式定义: 即定义一个创建对象的接口(即抽象工厂类),让其子类(具体工厂类)决定实例化哪一个类(具体产品类)."一对一"的关系 1,一抽象工厂类派生出多个具体工厂类: 2,一抽象产品类派生出多个具体产品类: 3,每个具体工厂类只能创建一个具体产品类的实例. UML图: 角色模块: 1,抽象工厂类:工厂方法模式的核心,定义一个创建对象的接口 2,具体工厂类:继承抽象工厂类,实现其工厂方法,实现具体业务逻辑 3,抽象产品类:是工厂方法模式所创建的产品的父类 4,具体产品类:实现抽象

工厂模式三部曲:抽象工厂模式

工厂模式三部曲:简单工厂模式 工厂模式三部曲:工厂方法模式 前言 这是工厂模式三部曲中的最后一篇了,在这篇文章中将会讲述抽象工厂模式,抽象工厂模式正如其名字一样,非常抽象.但是抽象工厂模式的功能却十分强大,对抽象工厂的利用也非常好. 这篇文章中会像本系列第一篇一样,给出普通实现方式和使用了反射机制的实现两种代码,并且会说明这两种实现方式的区别.并且在文章的最后,会将这三种模式放在一起,对这三种工厂模式进行总结. 本人理解可能不够深刻,这一系列文章中存在的问题,欢迎大家提出,谢谢! 什么是抽象工厂

人人都能看懂的工厂方法模式和抽象工厂模式的区别

设计模式中的工厂方法模式和抽象工厂模式一直不知不觉地使用在程序设计中,但是就是经常只有实践没有进行理论指导,所以感觉有一点半路子出家而没有系统学习过的不踏实的感觉.现在总结了一下之前项目中使用过的抽象工厂模式,加强对创建型模式中工厂模式的理解. 先举个栗子感性的理解工厂方法模式和抽象工厂模式这两者的区别. 有一个富商,在深圳开了三个手机厂,分别代工苹果手机,三星手机,华为手机.富商经常视察这3个厂,在苹果手机厂就说"大家要做好苹果手机",在三星厂就说"大家要做好三星手机&qu

工厂方法模式与抽象工厂模式

本文转自:http://laughingchs.iteye.com/blog/1169986 一.引子       话说十年前,有一个暴发户,他家有三辆汽车——Benz奔驰.Bmw宝马.Audi奥迪,还雇了司机为他开车.不过,暴发户坐车时总是怪怪的:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上Audi说“开奥迪车!”.你一定说:这人有病!直接说开车不就行了?!       而当把这个暴发户的行为放到我们程序设计中来时,会发现这是一个普遍存在的现象.幸运的是,这种有病