设计模式之三个工厂

在学习设计模式的过程中,看到了三个模式很相似的名称,这一篇博客,就拿它们在一起说说。
首先,这三个模式的名称分别是简单工厂、工厂方法和抽象工厂模式。对于前两个模式,感觉还比较好理解,抽象工厂模式真的很糊涂。也许,等这篇博客完工后,自己对它会更亲密些了。
首先说第一个简单工厂模式。从类型上来说,它应该属于创建型模式,但它并不包含在上篇23种模式总结的范围之中。至于为什么,自己也不清楚。这也就让自己想到了一个问题,模式的分类为什么分为创建、结构和行为三大类呢?这个问题可以在第三遍设计模式的时候思考思考。言归正传,还是回到简单工厂模式。
【简单工厂模式】其是由一个工厂对象决定创建出哪一种产品类的实例。
● 该模式中包含的角色及其职责:
① 工厂(Creator)角色:该模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
② 抽象产品(Product)角色:该模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
③ 具体产品(Concrete Product)角色:该模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。
● 该模式的最大优点:
工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。
● 该模式的缺点:
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则需要改变工厂类,也就相应地违背了开放-封闭原则。
● 该模式何时使用:
① 工厂类负责创建的对象比较少;
② 客户只知道传入工厂类的参数,对于如何创建对象不关心;
③ 由于很容易违反设计原则,所以一般只在很简单的情况下应用。
【工厂方法模式】其定义一个用于创建对象的接口,让子类决定实例化哪一个类。其使一个类的实例化延迟到其子类。
● 该模式中包含的角色及其职责:
① 工厂接口:该模式的核心,与调用者直接交互用来提供产品。
② 工厂实现:在编程中,其决定如何实例化产品。需要有多少种产品,就需要有多少个具体的工厂实现。
③ 产品接口:其主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。
④ 产品实现:实现产品接口的具体类,决定了产品在客户端中的具体行为。
● 该模式的优点:
① 可以使代码结构清晰,有效地封装变化。
② 对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以。至于具体的实现,调用者无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
③ 降低耦合度。
下面,就以大鸟和小菜一开始就讨论的一个计算器的程序为例,也正是因为这个程序,我才把更加清楚它们两个。
先用简单工厂模式的方法看如何实现计算器:
首先包含一个运算类:

public class Operation
        {
            private double _numberA = 0;
            private double _numberB = 0;
            public double NumberA
            {
                get { return _numberA; }
                set { _numberA = value; }
            }
            public double NumberB
            {
                get { return _numberB; }
                set { _numberB = value; }
            }
            public virtual double GetResult()
            {
                double result = 0;
                return result;
            }
        }
其次各个具体的加减乘除类都继承运算类:

 class OperationAdd : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA + NumberB;
                return result;
            }
        }
        class OperationSub : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA - NumberB;
                return result;
            }
        }

最后利用一个运算工厂类负责其中的实例化:


public class OperationFactory
        {
            public static Operation createOperate(string operate)
            {
                Operation oper = null;
                switch (operate)
                {
                    case "+":
                        oper = new OperationAdd();
                        break;
                    case "-":
                        oper = new OperationSub();
                        break;
                    case "*":
                        oper = new OperationMul();
                        break;
                    case "/":
                        oper = new OperationDiv();
                        break;
                }
                return oper;
            }
        }

这样的代码确实比面向过程方便很多,但是还是存在问题,比如现在想要增加一个其他的具体运算类,如求根,这下,就必须依靠修改代码去实现实例化,这也就违背了只扩展不修改的原则。
办法总比问题多,这样,第二个说的工厂方法模式就可以用来解决问题了。
下面看如何利用工厂方法模式的方法是如何实现计算器的:
首先是前者方法中的运算类和各个具体运算类保持不变;
其次增加一个工厂接口:


interface IFactory
{
       Operation CreateOperation();
}

最后加减乘除各建一个具体的工厂去实现这个接口:


//加法类工厂
class AddFactory:IFactory
{
        public Operation CreateOperation()
        {
              return new OperationAdd();
        }
}

//减法类工厂
class SubFactory:IFactory
{
        public Operation CreateOperation()
        {
              return new OperationAdd();
        }
}

这样的代码就解决了上面去修改代码的问题,如果是要增加一个其他的具体运算类,只需要添加一个它的运算工厂以及具体运算类本身就行,也就是扩展就行。
从两者的结构图看,也更加清晰一些:

到此,我们也可以很容易发现其实它们两者是极为相似的,区别也就是:简单工厂只有三个要素,它没有工厂接口,所以在工厂实现的扩展性方面弱,可以算是工厂方法模式的简化版吧。
第三个,抽象工厂模式。
【抽象工厂模式】提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
● 该模式何时使用:
当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?:读到这句话,自己才明白那么一点为什么有抽象工厂模式的出现了。
其提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂产品角色只负责一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
● 该模式优点:
① 分离了具体的类;
② 使得易于交换产品系列;
③ 有利于产品的一致性。
● 该模式缺点:
难以支持新种类的产品
对于其优点还是有些体会的。
下面以大鸟和小菜讨论的访问数据的例子,看看它与工厂方法模式间的差别。
先看用工厂方法模式实现数据访问程序:
其中包含IUser接口(用于客户端访问)和IFactory接口(用于访问User表对象的抽象的工厂接口)

//IUser接口
interface IUser
{
     void Insert(User user);

     User GetUser(int id);
}
//IFactory接口
interface IFactory
{
     IUser CreateUser();
}

另外,还有具体类(AccessUser)和具体工厂(AccessFactory)。


//AccessUser类
class AccessUser:IUser
{
     public void Insert(User user)
     {
         Console.WriteLine("在Access中给User表增加一条记录");
      }
      public User GetUser(int id)
      {
          Console.WriteLine("在Access中根据ID得到User表一条记录");
          return null;
       }
}
//AccessFactory类
class AccessFactory:IFactory
{
       public IUser CreateUser()
       {
             return new AccessUser();
       }
}

这样,就用工厂方法模式实现了对数据的访问。下面同样一个问题:如果要增加某一具体类,在这里也就是指访问数据库中的其他表呢?这就必将增加一个个类对应一个个表。
这时候,抽象工厂模式就来解决问题了。它实现不光是对User表的访问,同样访问Department表的访问。
大体上都和工厂方法一致,只是它又通过增加接口来实现。同样看看两者的结构图:

最后,大鸟和小菜的对话,很好地说明了两者的区别。
小菜以为后者也是工厂方法模式的实现,大鸟的回答是:
“只有一个User类和User操作类的时候,是只需要工厂方法模式的,但是现在数据库中有很多表,而SQL Server与Access又是两大不同的分类,所以解决这种涉及到多个产品系列的问题,有一个专门的工厂模式叫做抽象工厂模式。
至此,三个工厂的总结就结束了。现在,也确实对三个工厂的了解更加深入了些。学习这三个模式,也让我们看到了遇到问题,就相应地解决问题的重要性,否则编写的程序永远不会有所进步的。
时间: 2024-10-31 07:17:57

设计模式之三个工厂的相关文章

设计模式之三(工厂方法模式)

原文:设计模式之三(工厂方法模式) 前言 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化那一个类.工厂方法使一个类的实例化延迟到其子类. 简单工厂模式(http://www.cnblogs.com/aehyok/archive/2013/05/10/3072008.html)的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖. 工厂方法模式实现时,客户端需要决定实例化那一个工厂来实现运算类,选择判断的问题还是存在

javascript设计模式中的工厂模式示例

 这篇文章主要介绍了javascript设计模式中的工厂模式示例讲解,需要的朋友可以参考下 javaScript工厂方式原始的方式   因为对象的属性可以在对象创建后动态定义,这在 JavaScript 最初引入时都会编写类似下面的代码   代码如下: var oCar = new Object; oCar.color = "blue"; oCar.doors = 4; oCar.mpg = 25; oCar.showColor = function() {   alert(this.

设计模式: 简单工厂模式

引入: 在我们的思维中,会有一种习惯,当遇到某种问题时,会直接考虑用最直接的语言去去实现它,而往往忽略了整个程序的可维护性.可扩展性. 比如,我们写一个基本的计算器功能,要求能计算四则运算,大家或许会直接写: public class ProgramDemo{ public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(

乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)

原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)[索引页][源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) 作者:webabcd 介绍 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 示例 有Message和MessageModel,Message有一个Insert()方法,该方法的参数是MessageModel. AbstractMessageModel usi

C#设计模式(4)——抽象工厂模式

原文:C#设计模式(4)--抽象工厂模式 一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码),而工厂方法模式每个具体工厂类只完成单个实例的创建,所以它具有很好的可扩展性.但是在现实生活中,一个工厂只创建单个产品这样的例子很少,因为现在的工厂都多元化了,一个工厂创建一系列的产品,如果我们要设计这样的系统时,工厂方法模式显然在这里不适用,然后抽象工厂模式却可以很好地解决一系列产品创建的问题,这是本专

Android设计模式系列之工厂方法模式_Android

工厂方法模式,往往是设计模式初学者入门的模式,的确,有人称之为最为典型最具启发效果的模式. android中用到了太多的工厂类,其中有用工厂方法模式的,当然也有很多工厂并不是使用工厂方法模式的,只是工具管理类. 今天以ThreadFactory举例说明一下简单工厂模式和工厂方法模式. 工厂方法模式,Factory Method,简单的方式,不简单的应用. 1.意图 定义一个用于创建对象的接口,让子类决定实例化哪个类.工厂方式模式使一个类的实例化延迟到其子类. 热门词汇:虚构造器 延迟 创建对象

C#设计模式(2)——简单工厂模式

原文:C#设计模式(2)--简单工厂模式 一.引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式--简单工厂模式. 二.简单工厂模式的介绍 说到简单工厂,自然的第一个疑问当然就是什么是简单工厂模式了? 在现实生活中工厂是负责生产产品的,同样在设计模式中,简单工厂模式我们也可以理解为负责生产对象的一个类, 我们平常编程中,当使用"new"关键字创建一个对象时,此时该类就依赖与

设计模式之四(抽象工厂模式第三回合)

原文:设计模式之四(抽象工厂模式第三回合) 前言 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂模式最大的好处便是易于交换产品系列,由于具体工厂类,例如IFactory factory=new AccessFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置.我们的设计不能去防止需要的变更,那么我们的理想便是让改动变得最小,那么现在如果你要更改数据库访问,

设计模式之四(抽象工厂模式第一回合)

原文:设计模式之四(抽象工厂模式第一回合) 前言 首先关于抽象工厂模式的学习,我们需要慢慢的,由浅入深的进入.不能单刀直入,否则可能达不到预期学明白的目标. 第一回合  首先我们从最简单的数据访问程序开始吧. 下面先来看一个简单的小例子,代码很简单 public class User { public int ID{get;set;} public string Name{get;set;} } 一个简单的实体类,也相当于在SqlServer数据库中建立了相同的数据表 public class