zoukankan      html  css  js  c++  java
  • 抽象工厂模式

    【1】什么是抽象工厂模式?

    原文:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

    所有专业书上都是这句话:“为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。”

    逐级分解一下:

    1、为创建一组相关的对象提供一个接口,而且无需指定他们的具体类。

    2、为创建一组相互依赖的对象提供一个接口,而且无需指定他们的具体类。

    3、为创建对象提供一个接口,而且无需指定他们的具体类。

    4、为创建对象提供一个接口。

    5、一个接口。

    抽象工厂:抽象是指接口,工厂是指集合,其实是接口集合。

    既然是接口集合,那么属于哪种类型的接口集合?即具体工厂类。

    比如SqlFactory,是指Sql数据库的接口集合。

    而Sql数据库的接口集合最终都可以创建出哪种类型的Sql产品?即具体产品类。

    比如SqlUser,SqlDepartment,是指具体的Sql产品类。

    所以,抽象工厂,即创建出产品类的接口集合。

    比如,IFactory,创建出产品类的接口集合,不可以实例化对象,仅仅提供接口规范。

    每个具体工厂,即创建出同一类产品的功能集合。

    比如,SqlFactory,创建出同一类产品SqlUser、SqlDepartment的功能集合。

    【2】抽象工厂模式的逻辑结构图及代码示例:

    逻辑结构图:

    代码示例:

      1 #include <string>
      2 #include <iostream>
      3 using namespace std;
      4 
      5 // 抽象产品类1
      6 class IUser
      7 {
      8 public:
      9     virtual void getUser() = 0;
     10     virtual void setUser() = 0;
     11 };
     12 
     13 // 具体产品类1(SqlUser)
     14 class SqlUser : public IUser
     15 {
     16 public:
     17     void getUser()
     18     {
     19         cout << "在sql中返回user" << endl;
     20     }
     21     void setUser()
     22     {
     23         cout << "在sql中设置user" << endl;
     24     }
     25 };
     26 
     27 // 具体产品类1(AccessUser)
     28 class AccessUser : public IUser
     29 {
     30 public:
     31     void getUser()
     32     {
     33         cout << "在Access中返回user" << endl;
     34     }
     35     void setUser()
     36     {
     37         cout << "在Access中设置user" << endl;
     38     }
     39 };
     40 
     41 // 抽象产品类2
     42 class IDepartment
     43 {
     44 public:
     45     virtual void getDepartment() = 0;
     46     virtual void setDepartment() = 0;
     47 };
     48 
     49 // 具体产品类2(SqlDepartment)
     50 class SqlDepartment : public IDepartment
     51 {
     52 public:
     53     void getDepartment()
     54     {
     55         cout << "在sql中返回Department" << endl;
     56     }
     57     void setDepartment()
     58     {
     59         cout << "在sql中设置Department" << endl;
     60     }
     61 };
     62 
     63 // 具体产品类2(AccessDepartment)
     64 class AccessDepartment : public IDepartment
     65 {
     66 public:
     67     void getDepartment()
     68     {
     69         cout << "在Access中返回Department" << endl;
     70     }
     71     void setDepartment()
     72     {
     73         cout << "在Access中设置Department" << endl;
     74     }
     75 };
     76 
     77 // 抽象工厂类
     78 class IFactory
     79 {
     80 public:
     81     virtual IUser *createUser() = 0;
     82     virtual IDepartment *createDepartment() = 0;
     83 };
     84 
     85 // 具体工厂类(SqlFactory)
     86 class SqlFactory : public IFactory
     87 {
     88 public:
     89     IUser *createUser() 
     90     {
     91         return new SqlUser(); // 创建具体产品1(SqlUser)
     92     }
     93     IDepartment *createDepartment() 
     94     {
     95         return new SqlDepartment(); // 创建具体产品2(SqlDepartment)
     96     }
     97 };
     98 
     99 // 具体工厂类(AccessFactory)
    100 class AccessFactory : public IFactory
    101 {
    102 public:
    103     IUser *createUser()
    104     {
    105         return new AccessUser(); // 创建具体产品1(AccessUser)
    106     }
    107     IDepartment *createDepartment() 
    108     {
    109         return new AccessDepartment(); // 创建具体产品2(AccessDepartment)
    110     }
    111 };
    112 
    113 void main()
    114 {
    115     IFactory *pFactory = NULL;
    116     IUser *pUser = NULL;
    117     IDepartment *pDepartment = NULL;
    118 
    119     pFactory = new AccessFactory();
    120     if (NULL == pFactory)
    121     {
    122         return;
    123     }
    124 
    125     pUser = pFactory->createUser();
    126     if (NULL == pUser)
    127     {
    128         return;
    129     }
    130     pDepartment = pFactory->createDepartment();
    131     if (NULL == pDepartment)
    132     {
    133         return;
    134     }
    135 
    136     pUser->getUser();
    137     pUser->setUser();
    138     pDepartment->getDepartment();
    139     pDepartment->setDepartment();
    140     
    141     delete pFactory;
    142     pFactory = NULL;
    143     delete pUser;
    144     pUser = NULL;
    145     delete pDepartment;
    146     pDepartment = NULL;
    147 
    148     system("pause");
    149 }
    150 
    151 // run out:
    152 /*
    153 在Access中返回user
    154 在Access中设置user
    155 在Access中返回Department
    156 在Access中设置Department
    157 请按任意键继续. . .
    158 */

    抽象产品类、抽象工厂类、具体产品类、具体工厂类如上注释。

    【3】抽象工厂模式结构图

    结构图如下所示:

    为了加深宏观的理解,特搜了这张图贴上。

    【4】工厂方法模式与抽象工厂模式的区别

    详细对比请参见下图:

    抽象工厂模式更难理解,需要用心琢磨,仔细体会。

    【5】抽象工厂模式的优点和缺点

    抽象工厂模式的优点:

    1、便于交换产品系。

    由于具体工厂类,例如IFactory factory = new SqlFactory(),在一个应用中只需要在初始化时出现一次。

    这就使得改变一个应用的具体工厂变得很简单,而想要使用不同的产品配置只需要改变具体工厂即可。

    2、客户端与具体创建实例过程分离。

    客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。

    抽象工厂模式的缺点(程序也是很有原则性的,比如:开放-封闭原则):

    针对第一点优点,试想第一点(封闭原则,对于修改尽量关闭):客户端程序显然不可能只有一处使用IUser或IDepartment。

    而如此设计,如果有100处调用了数据库访问类呢?是不是就需要更改100次IFactory factory = new AccessFactory()这样的代码才行?

    很明显,不能满足我们想改动一处就完全达到要求的目的。

    第二点(开放原则,对于扩展尽量开放):仅仅能很方便的切换数据库访问代码是很有局限性的,假设用户的需求改变需要增加功能,比如增加项目表Project。

    先明确一下需要改动的地方。至少增加三个类,IProject、SqlserverProject、AccessProject,还需要更改IFactory、SqlserverFactory、AccessFactory才可以完全满足要求。

    以上俩个缺点,又让我们陷入深深的沉思。

    【6】改进方案1:简单工厂改进抽象工厂

    代码示例如下:

      1 #include <string>
      2 #include <iostream>
      3 using namespace std;
      4 
      5 // 抽象产品类1
      6 class IUser
      7 {
      8 public:
      9     virtual void getUser() = 0;
     10     virtual void setUser() = 0;
     11 };
     12 
     13 // 具体产品类1(SqlUser)
     14 class SqlUser : public IUser
     15 {
     16 public:
     17     void getUser()
     18     {
     19         cout << "在sql中返回user" << endl;
     20     }
     21     void setUser()
     22     {
     23         cout << "在sql中设置user" << endl;
     24     }
     25 };
     26 
     27 // 具体产品类1(AccessUser)
     28 class AccessUser : public IUser
     29 {
     30 public:
     31     void getUser()
     32     {
     33         cout << "在Access中返回user" << endl;
     34     }
     35     void setUser()
     36     {
     37         cout << "在Access中设置user" << endl;
     38     }
     39 };
     40 
     41 // 抽象产品类2
     42 class IDepartment
     43 {
     44 public:
     45     virtual void getDepartment() = 0;
     46     virtual void setDepartment() = 0;
     47 };
     48 
     49 // 具体产品类2(SqlDepartment)
     50 class SqlDepartment : public IDepartment
     51 {
     52 public:
     53     void getDepartment()
     54     {
     55         cout << "在sql中返回Department" << endl;
     56     }
     57     void setDepartment()
     58     {
     59         cout << "在sql中设置Department" << endl;
     60     }
     61 };
     62 
     63 // 具体产品类2(AccessDepartment)
     64 class AccessDepartment : public IDepartment
     65 {
     66 public:
     67     void getDepartment()
     68     {
     69         cout << "在Access中返回Department" << endl;
     70     }
     71     void setDepartment()
     72     {
     73         cout << "在Access中设置Department" << endl;
     74     }
     75 };
     76 
     77 // 工厂方法类
     78 class DataAccess
     79 {
     80 private:
     81     static string db;
     82 
     83 public:
     84     static IUser *createUser()
     85     {
     86         if (db == "sql")
     87         {
     88             return new SqlUser();
     89         }
     90         else if (db == "access")
     91         {
     92             return new AccessUser();
     93         }
     94 
     95         return NULL;
     96     }
     97 
     98     static IDepartment *createDepartment()
     99     {
    100         if (db == "sql")
    101         {
    102             return new SqlDepartment();
    103         }
    104         else if (db == "access")
    105         {
    106             return new AccessDepartment();
    107         }
    108 
    109         return NULL;
    110     }
    111 };
    112 
    113 string DataAccess::db = "sql";
    114 
    115 void main()
    116 {
    117     IUser *pUser = NULL;
    118     IDepartment *pDepartment = NULL;
    119 
    120     pUser = DataAccess::createUser();
    121     if (NULL == pUser)
    122         return;
    123 
    124     pDepartment = DataAccess::createDepartment();
    125     if (NULL == pDepartment)
    126         return;
    127 
    128     pUser->getUser();
    129     pUser->setUser();
    130     pDepartment->getDepartment();
    131     pDepartment->setDepartment();
    132 
    133     delete pUser;
    134     pUser = NULL;
    135     delete pDepartment;
    136     pDepartment = NULL;
    137 
    138     system("pause");
    139 }
    140 
    141 // run out:
    142 /*
    143 在sql中返回user
    144 在sql中设置user
    145 在sql中返回Department
    146 在sql中设置Department
    147 请按任意键继续. . .
    148 */

    利用DataAccess(数据访问)类替换掉了IFactory、SqlserverFactory、AccessFactory三个工厂类。

    【7】改进方案2:配置文件 + 抽象工厂模式

    Good Good Study, Day Day Up.

    顺序 选择 循环 总结

  • 相关阅读:
    【Sparse】关于__attribute__((bitwise)),__le32,__be32等的理解【转】
    设备树中ranges属性分析(1)【转】
    Linux内核API sprint_symbol【转】
    Linux内核--网络协议栈深入分析(二)--sk_buff的操作函数【转】
    浅析SkipList跳跃表原理及代码实现【转】
    关于kernel module签名【转】
    apt-get 更新指定软件_Linux系统 aptget 命令的使用:安装、更新、卸载软件包【转】
    如何挂载ubi文件系统【转】
    伙伴系统之伙伴系统概述--Linux内存管理(十五)【转】
    精确时间协议PTP研究【转】
  • 原文地址:https://www.cnblogs.com/Braveliu/p/3946808.html
Copyright © 2011-2022 走看看