设计模式1(C++) 三种工厂模式

 设计模式的一些基本原则:

设计模式的六大原则(开闭原则、里氏代换原则、依赖倒转原则、单一职责原则、接口隔离原则、迪米特法则

  1. 单一职责原则
    1. 一个类只有一个职责,不应既做这又做那,这样的好处是:

    2. 降低了类的复杂性

    3. 提高了代码的可读性,可维护性

    4. 降低了因变更带来的风险

  2. 里氏替换原则
    1. 一个子类必须实现父类的所有方法

    2. 一个子类可以拥有父类没有的方法

    3. 在所有需要父类对象的地方都可以用子类的对象替换而不会出现问题

  3. 依赖倒置原则
    1. 高层模块不应该依赖底层模块

    2. 抽象不应该依赖于细节

    3. 实现应该依赖于抽象

    4. 面向接口编程
  4. 接口隔离原则
    1. 一个类可以有多个方法,但如果打算向外部提供部分方法,则把这些方法实现为接口,返回接口类型
  5. 迪米特法则
    1. 最少知识法则
    2. 只与你直接的朋友通信
    3. 一个类不应该与过多的类发生联系
    4. 如果一个类需要调用第三个类的方法,可以加入中间者,转发调用这个方法
  6. 开关原则
    1. 最重要的一个核心原则
    2. 一个软件实体应该对扩展开放,对修改封闭
  7. 组合优先于继承

  8. 把变与不变的事物分开

 

 

1. 工厂模式

软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。最近看设计模式的书,对于每个模式,用C++写了个小例子,加深一下理解。主要参考《大话设计模式》和《设计模式:可复用面向对象软件的基础》两本书。本文介绍工厂模式的实现。

       工厂模式属于创建型模式,大致可以分为三类,简单工厂模式、工厂方法模式、抽象工厂模式。听上去差不多,都是工厂模式。下面一个个介绍,首先介绍简单工厂模式,它的主要特点是需要在工厂类中做判断,从而创造相应的产品。当增加新的产品时,就需要修改工厂类。有点抽象,举个例子就明白了。有一家生产处理器核的厂家,它只有一个工厂,能够生产两种型号的处理器核。客户需要什么样的处理器核,一定要显示地告诉生产工厂。下面给出一种实现方案。

 

 1 #include <iostream>
 2 #include <chrono>
 3 #include <thread>
 4 #include <mutex>
 5 #include <pthread.h>
 6 #include <unistd.h>
 7 #include <stdio.h>
 8 #include <stdlib.h>
 9 #include <string.h>
10 #include <error.h>
11 #include <vector>
12 #include <algorithm>
13 #include <sstream>
14 #include <string>
15 using namespace std;
16 
17 
18 enum CTYPE {COREA, COREB};
19 class CSingleCore
20 {
21 public:
22     CSingleCore(){ cout << "CSingleCore()" << endl; }
23     /* C++析构函数的自动调用(析构函数必须是虚拟的,这样删除父类指针指向的子类对象,
24      * 才能同时调用两者的析构函数,否则就没有机会调用子类析构函数)
25      * 因此,建议子类继承父类时,父类的析构函数为虚函数.
26      * 有些情况下,如果父类的析构函数不是虚函数,那么就会没有机会调用子类析构函数,造成内存泄漏.
27      */
28     virtual ~CSingleCore(){ cout << "~CSingleCore()" << endl; }
29     virtual void Show() = 0;
30 };
31 //单核A
32 class CSingleCoreA: public CSingleCore
33 {
34 public:
35     CSingleCoreA(){ cout << "CSingleCoreA()" << endl; }
36     ~CSingleCoreA(){ cout << "~CSingleCoreA()" << endl; }
37     void Show() { cout<<"CSingleCoreA Show()"<<endl; }
38 };
39 //单核B
40 class CSingleCoreB: public CSingleCore
41 {
42 public:
43     CSingleCoreB(){ cout << "CSingleCoreB()" << endl; }
44     ~CSingleCoreB(){ cout << "~CSingleCoreB()" << endl; }
45     void Show() { cout<<"CSingleCoreB Show()"<<endl; }
46 };
47 //唯一的工厂,可以生产两种型号的处理器核,在内部判断
48 class CFactory
49 {
50 public:
51     CSingleCore* CreateCSingleCore(enum CTYPE ctype)
52     {
53         if(ctype == COREA) //工厂内部判断
54             return new CSingleCoreA(); //生产核A
55         else if(ctype == COREB)
56             return new CSingleCoreB(); //生产核B
57         else
58             return NULL;
59     }
60 };
61 
62 int main(int argc, char *argv[])
63 {
64     CFactory fy;
65     CSingleCore *sc = fy.CreateCSingleCore(COREB);
66     sc->Show();
67     delete sc;
68     sc = NULL;
69     return 0;
70 }
简单工厂模式

 

 这样设计的主要缺点之前也提到过,就是要增加新的核类型时,就需要修改工厂类。这就违反了开放封闭原则:软件实体(类、模块、函数)可以扩展,但是不可修改。于是,工厂方法模式出现了。所谓工厂方法模式,是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类

       听起来很抽象,还是以刚才的例子解释。这家生产处理器核的产家赚了不少钱,于是决定再开设一个工厂专门用来生产B型号的单核,而原来的工厂专门用来生产A型号的单核。这时,客户要做的是找好工厂,比如要A型号的核,就找A工厂要;否则找B工厂要,不再需要告诉工厂具体要什么型号的处理器核了。下面给出一个实现方案。

 

  1 #include <iostream>
  2 #include <chrono>
  3 #include <thread>
  4 #include <mutex>
  5 #include <pthread.h>
  6 #include <unistd.h>
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 #include <string.h>
 10 #include <error.h>
 11 #include <vector>
 12 #include <algorithm>
 13 #include <sstream>
 14 #include <string>
 15 using namespace std;
 16 
 17 
 18 enum CTYPE {COREA, COREB};
 19 class CProduct
 20 {
 21 public:
 22     CProduct(){ cout << "CProduct()" << endl; }
 23     /* C++析构函数的自动调用(析构函数必须是虚拟的,这样删除父类指针指向的子类对象,
 24      * 才能同时调用两者的析构函数,否则就没有机会调用子类析构函数)
 25      * 因此,建议子类继承父类时,父类的析构函数为虚函数.
 26      * 有些情况下,如果父类的析构函数不是虚函数,那么就会没有机会调用子类析构函数,造成内存泄漏.
 27      */
 28     virtual ~CProduct(){ cout << "~CProduct()" << endl; }
 29     virtual void Show() = 0;
 30 };
 31 //单核A
 32 class CProductA: public CProduct
 33 {
 34 public:
 35     CProductA(){ cout << "CProductA()" << endl; }
 36     ~CProductA(){ cout << "~CProductA()" << endl; }
 37     void Show() { cout<<"CProductA Show()"<<endl; }
 38 };
 39 //单核B
 40 class CProductB: public CProduct
 41 {
 42 public:
 43     CProductB(){ cout << "CProductB()" << endl; }
 44     ~CProductB(){ cout << "~CProductB()" << endl; }
 45     void Show() { cout<<"CProductB Show()"<<endl; }
 46 };
 47 // 简单工厂模式.唯一的工厂,可以生产两种型号的处理器核,在内部判断
 48 class CSimpleFactory
 49 {
 50 public:
 51     CSimpleFactory(){ cout << "CSimpleFactory()" << endl; }
 52     ~CSimpleFactory(){ cout << "~CSimpleFactory()" << endl; }
 53     CProduct* CreateCProduct(enum CTYPE ctype)
 54     {
 55         if(ctype == COREA) //工厂内部判断
 56             return new CProductA(); //生产核A
 57         else if(ctype == COREB)
 58             return new CProductB(); //生产核B
 59         else
 60             return NULL;
 61     }
 62 };
 63 
 64 // 工厂方法模式
 65 class CFactoryMethod
 66 {
 67 public:
 68     CFactoryMethod(){ cout << "CFactoryMethod()" << endl; }
 69     virtual ~CFactoryMethod(){ cout << "~CFactoryMethod()" << endl; }
 70     virtual CProduct* CreateProduct() = 0;
 71 };
 72 
 73 //生产A核的工厂
 74 class CFactoryA : public CFactoryMethod
 75 {
 76 public:
 77     CFactoryA(){  cout << "CFactoryA()" << endl; }
 78     ~CFactoryA(){  cout << "~CFactoryA()" << endl; }
 79     CProduct* CreateProduct() {
 80         return new CProductA();
 81     }
 82 };
 83 
 84 //生产B核的工厂
 85 class CFactoryB : public CFactoryMethod
 86 {
 87 public:
 88     CFactoryB(){  cout << "CFactoryB()" << endl; }
 89     ~CFactoryB(){  cout << "~CFactoryB()" << endl; }
 90     CProduct* CreateProduct() {
 91         return new CProductB();
 92     }
 93 };
 94 
 95 int main(int argc, char *argv[])
 96 {
 97     // simple factory
 98 //    CSimpleFactory fy;
 99 //    CProduct *sc = fy.CreateCProduct(COREB);
100 //    sc->Show();
101 //    delete sc;
102 //    sc = NULL;
103 
104     // factory method
105     CFactoryMethod *fma = new CFactoryA();
106     CProduct *scm = fma->CreateProduct();
107     scm->Show();
108 
109     delete scm;
110     scm = NULL;
111 
112     delete fma;
113     fma = NULL;
114     return 0;
115 }
工厂方法模式

 

工厂方法模式也有缺点,每增加一种产品,就需要增加一个对象的工厂。如果这家公司发展迅速,推出了很多新的处理器核,那么就要开设相应的新工厂。在C++实现中,就是要定义一个个的工厂类。显然,相比简单工厂模式,工厂方法模式需要更多的类定义。

       既然有了简单工厂模式和工厂方法模式,为什么还要有抽象工厂模式呢?它到底有什么作用呢?还是举这个例子,这家公司的技术不断进步,不仅可以生产单核处理器,也能生产多核处理器。现在简单工厂模式和工厂方法模式都鞭长莫及。抽象工厂模式登场了。它的定义为提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。具体这样应用,这家公司还是开设两个工厂,一个专门用来生产A型号的单核多核处理器,而另一个工厂专门用来生产B型号的单核多核处理器,下面给出实现的代码。

 

  1 #include <iostream>
  2 #include <chrono>
  3 #include <thread>
  4 #include <mutex>
  5 #include <pthread.h>
  6 #include <unistd.h>
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 #include <string.h>
 10 #include <error.h>
 11 #include <vector>
 12 #include <algorithm>
 13 #include <sstream>
 14 #include <string>
 15 using namespace std;
 16 
 17 enum CTYPE {COREA, COREB};
 18 class CSingleCore
 19 {
 20 public:
 21     CSingleCore(){ cout << "CSingleCore()" << endl; }
 22     /* C++析构函数的自动调用(析构函数必须是虚拟的,这样删除父类指针指向的子类对象,
 23      * 才能同时调用两者的析构函数,否则就没有机会调用子类析构函数)
 24      * 因此,建议子类继承父类时,父类的析构函数为虚函数.
 25      * 有些情况下,如果父类的析构函数不是虚函数,那么就会没有机会调用子类析构函数,造成内存泄漏.
 26      */
 27     virtual ~CSingleCore(){ cout << "~CSingleCore()" << endl; }
 28     virtual void Show() = 0;
 29 };
 30 //单核A
 31 class CSingleCoreA: public CSingleCore
 32 {
 33 public:
 34     CSingleCoreA(){ cout << "CSingleCoreA()" << endl; }
 35     ~CSingleCoreA(){ cout << "~CSingleCoreA()" << endl; }
 36     void Show() { cout<<"CSingleCoreA Show()"<<endl; }
 37 };
 38 //单核B
 39 class CSingleCoreB: public CSingleCore
 40 {
 41 public:
 42     CSingleCoreB(){ cout << "CSingleCoreB()" << endl; }
 43     ~CSingleCoreB(){ cout << "~CSingleCoreB()" << endl; }
 44     void Show() { cout<<"CSingleCoreB Show()"<<endl; }
 45 };
 46 
 47 class CMultiCore
 48 {
 49 public:
 50     CMultiCore() { cout << "CMultiCore()" << endl; }
 51     virtual ~CMultiCore() { cout << "~CMultiCore()" << endl; }
 52     virtual void Show() = 0;
 53 };
 54 
 55 class MultiCoreA : public CMultiCore
 56 {
 57 public:
 58     MultiCoreA() {cout << "MultiCoreA()" << endl;}
 59     ~MultiCoreA() {cout << "~MultiCoreA()" << endl;}
 60     void Show() {cout<<"MultiCoreA Show()"<<endl;}
 61 };
 62 
 63 class MultiCoreB : public CMultiCore
 64 {
 65 public:
 66     MultiCoreB() {cout << "MultiCoreB()" << endl;}
 67     ~MultiCoreB() {cout << "~MultiCoreB()" << endl;}
 68     void Show() { cout<<"MultiCoreB Show()"<<endl; }
 69 };
 70 
 71 class CoreFactory
 72 {
 73 public:
 74     CoreFactory(){cout << "CoreFactory()" << endl;}
 75     virtual ~CoreFactory(){cout << "~CoreFactory()" << endl;}
 76     virtual CSingleCore* CreateSingleCore() = 0;
 77     virtual CMultiCore* CreateMultiCore() = 0;
 78 };
 79 
 80 //工厂A,专门用来生产A型号的处理器
 81 class CFactoryA : public CoreFactory
 82 {
 83 public:
 84     CFactoryA(){  cout << "CFactoryA()" << endl; }
 85     ~CFactoryA(){  cout << "~CFactoryA()" << endl; }
 86     CSingleCore* CreateSingleCore() {
 87         return new CSingleCoreA();
 88     }
 89      CMultiCore* CreateMultiCore() { return new MultiCoreA(); }
 90 };
 91 
 92 //工厂B,专门用来生产B型号的处理器
 93 class CFactoryB : public CoreFactory
 94 {
 95 public:
 96     CFactoryB(){  cout << "CFactoryB()" << endl; }
 97     ~CFactoryB(){  cout << "~CFactoryB()" << endl; }
 98     CSingleCore* CreateSingleCore() {
 99         return new CSingleCoreB();
100     }
101     CMultiCore* CreateMultiCore() { return new MultiCoreB(); }
102 };
103 
104 int main(int argc, char *argv[])
105 {
106     CoreFactory *cfy = new CFactoryB();
107     CMultiCore *mc = cfy->CreateMultiCore();
108     mc->Show();
109     if(mc != NULL)
110     {
111         delete mc;
112         mc = NULL;
113     }
114     if(cfy != NULL)
115     {
116         delete cfy;
117         cfy = NULL;
118     }
119     return 0;
120 }
抽象工厂模式

 

 

  至此,工厂模式介绍完了。利用Rational Rose 2003软件,给出三种工厂模式的UML图,加深印象。        

简单工厂模式的UML图:

         工厂方法的UML图:

         抽象工厂模式的UML图:

 

设计模式

设计模式资料2

设计模式资料3

设计模式的一些原则

 http://ftp.jaist.ac.jp/pub/eclipse/technology/epp/downloads/release/kepler/SR2/eclipse-cpp-kepler-SR2-linux-gtk-x86_64.tar.gz

 本文摘自15s

posted @ 2017-08-01 23:10  PKICA  阅读(69)  评论(0编辑  收藏  举报