zoukankan      html  css  js  c++  java
  • 简单工厂,工厂方法与抽象工厂模式区别与联系(汇总)

          设计模式作为程序员的内功心法,相信每个写过OOP代码的都不会陌生,不过有些模式之间既有区别,又有联系,我们来看看简单工厂,工厂方法与抽象工厂的区别和联系。

    一、简单工厂

          简单工厂模式中工厂为具体工厂,产品为抽象产品,由工厂实例创建产品实例。

    二、工厂方法

          工厂方法中有抽象的工厂类,一种抽象的产品类,而工厂类中仅创建此抽象产品类的实例,具体产品实例由具体的工厂类创建。

    三、抽象工厂

         抽象工厂创建多类产品,可将这些产品理解为一套相关的产品,由工厂在创建时一起创建,每类产品有不同的实例。实践中一般会用反射来创建工厂的实例,配合配置文件或依赖注入容器来避免创建不同产品时还需要修改客户端代码,即符合“修改封闭,扩展开放原则”,一点拙见,欢迎指正。

    以下转自terryLee的博客:

         

    概述

    在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时由于需求的变化,往往存在着更多系列对象的创建工作。如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?这就是我们要说的抽象工厂模式。

    意图

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

    模型图

    逻辑模型: 
                             
    物理模型:

                                       

          利用设计模式可以使我们的代码更灵活,更容易扩展,更容易维护。各种面向对象的程序设计语言都提供了基本相同的机制:比如类、继承、派生、多态等等。但是又有各自的特色,C# 中的反射机制便是一个很重要的工具,好好地利用就可以在实际中发挥很大的作用。

       我们来看一个例子:

       我的程序中有需要一系列的对象,比如apple,orange…, 要想利用他们,我们就必须在程序中根据用户要求,然后一个个调用 new 操作符来生成他们,这样客户程序就要知道相应的类的信息,生成的代码显然不够灵活。我们可以在代码中不利用具体的类,而只是说明我们需要什么,然后就能够得到我们想要的对象吗?

       哦,我们都看设计模式,听吧,很多人都在那里鼓吹他们是如何如何的棒,我们看看怎么样利用他们来解决问题。目标明确了,那我们看看哪个能够符合我们的要求。GoF的《设计模式》都看过吧,似懂非懂的看了一些,那我们看看能够不能够“凑”上去呢?J 嗯,我们的程序考虑的是对象怎么创建的,创建型模式应该符合要求吧。然后我们浏览一下各模式的“意图”部分。呵呵,第一个好像就撞到彩了,抽象工厂,我们看看吧,“提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类”,至少“无需指定它们具体的类”符合我们的要求。来看看它的结构(上图)

       我们的问题好像用不到这么复杂吧,只有orange,apple等等(应该就是product了),他们显然是一类的,都是fruit,我们只要一个生产水果的工厂就可以,左边的继承层次不要,只有一个FruitFactroy看看行不,先别管它正统不正统,实用就行J

       下面的一些东西显然是我们需要的:

    Public interface IFruit
    {
    }

    public class Orange:IFruit
    {
      public Orange()
      {
       Console.WriteLine("An orange is got!");
      }
    }

    public class Apple:IFruit
    {
      public Apple()
      {
       Console.WriteLine("An apple is got!");
      }
    }

       我们的FruitFactory应该是怎么样呢?上面的结构图中它给的是CreateProductA,那好,我就MakeOrange,还有一个CreateProductB,俺MakeOrange还不行??

    public class FruitFactory
    {
      public Orange MakeOrange()
      {
       return new Orange();
      }
      public Apple MakeApple()
      {
       return new Apple();
      }
    }

       怎么使用这个工厂呢?我们来写下面的代码:

    string FruitName = Console.ReadLine();
    IFruit MyFruit = null;
    FruitFactory MyFruitFactory = new FruitFactory();

    switch (FruitName)
    {
      case "Orange":
       MyFruit = MyFruitFactory.MakeOrange();
       break;
      case "Apple":
       MyFruit = MyFruitFactory.MakeApple();
       break;
      default:
       break;
    }

       编译运行,然后在控制台输入想要的东西,呵呵,成功了。沉浸在幸福中的你得意忘形了吧。
       不过等等,它好像还不完美,我如果想要pear,我既要在客户代码中的switch中加入判断,又要在工厂方法中加入MakePear方法,好像不怎么优雅。更好一点,在工厂中只提供一个方法,MakeFruit,然后传递进一个参数Name,代表我们想要的水果的名称,这样的话,似乎我们的客户代码中的那个switch就可以不要了,相反,在FruitFactory中好像需要一个,还等什么呢?实现吧。

    FruitFactory:
    public class FruitFactory
    {
      public IFruit MakeFruit(string Name)
      {
       switch (Name)
       {
        case "Orange":
         return new Orange();
        case "Apple":
         return new Apple();
        default:
         return null;
       }
      }
    }

       客户代码:

    string FruitName = Console.ReadLine();
    IFruit MyFruit;
    FruitFactory MyFruitFactory = new FruitFactory();
    MyFruit = MyFruitFactory.MakeFruit(FruitName);

       这样看起来好多了,至少我客户代码中不要再写那么一长串的判断代码了。

       阿Q精神又在起作用,我们又沉浸在成功的喜悦中了。 嗯,代码好像可以,应该没有什么改进了。但是好像又有另外一个声音在说:

       “除了一点……”

       “嗯? 等等,什么?”

       “FruitFactory也有switch啊,看起来也ugly啊!”

       “哼,肯定是看《重构》或者是《TDD》了,怎么要求那么苛刻!反正闲着也是闲着,看看可以改不?”

       既然不要条件判断,传入的只有水果的名称,假如Name = “Apple”,要生成一个Apple的对象,我需要new Apple(),如果我能够这样多好: new MakeItToClass(Name),把字符串转换成一个类。C#中虽然没有上述语法,但是提供了相应的机制,那就是反射。其中一个重要的类就是System.Type类,它对于反射起着核心的作用。我们可以使用 Type 对象的方法、字段、属性和嵌套类来查找有关该类型的所有信息。

       另外一个重要的类就是System.Activator,它包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。

       我们可以先利用Type类获取Name指定的类名的类的Type信息,然后可以根据这个信息利用Activator创建对象。还等什么呢?

    public class FruitFactory
    {
      public IFruit MakeFruit(string Name)
      {
       IFruit MyFruit = null;
       try
       {
        Type type = Type.GetType(Name,true);
        MyFruit = (IFruit)Activator.CreateInstance(type);
       }
       catch (TypeLoadException e)
        Console.WriteLine("I dont know this kind of fruit,exception caught - {0}" ,e.Message);
        return MyFruit;
      }
    }

       经过这样的处理以后,增加新的水果的时候,我们不需要修改客户代码了,同时工厂的代码也不需要修改了!

    运用样例
    AbstractMessageModel:

    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// 抽象Message实体类(AbstractProduct)
      /// </summary>
      public abstract class AbstractMessageModel
      {
        /**//// <summary>
        /// 构造函数
        /// </summary>
        public AbstractMessageModel()
        {
      
        }
      
        /**//// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="msg">Message内容</param>
        /// <param name="pt">Message发布时间</param>
        public AbstractMessageModel(string msg, DateTime pt)
        {
          this._message = msg;
          this._publishTime = pt;
        }
      
        private string _message;
        /**//// <summary>
        /// Message内容
        /// </summary>
        public string Message
        {
          get { return _message; }
          set { _message = value; }
        }
      
        private DateTime _publishTime;
        /**//// <summary>
        /// Message发布时间
        /// </summary>
        public DateTime PublishTime
        {
          get { return _publishTime; }
          set { _publishTime = value; }
        }
      
        /**//// <summary>
        /// UserId
        /// </summary>
        public abstract string UserId
        {
          get;
          set;
        }
      }
    }


    SqlMessageModel:

    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// SqlMessage实体类(Product)
      /// </summary>
      public class SqlMessageModel : AbstractMessageModel
      {
        /**//// <summary>
        /// 构造函数
        /// </summary>
        public SqlMessageModel()
          : base()
        {
      
        }
      
        /**//// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="userId">UserId</param>
        /// <param name="msg">Message内容</param>
        /// <param name="pt">Message发布时间</param>
        public SqlMessageModel(string userId, string msg, DateTime pt)
          : base(msg, pt)
        {
          this._userId = userId;
        }
      
        private string _userId;
        /**//// <summary>
        /// Message内容
        /// </summary>
        public override string UserId
        {
          get { return _userId; }
          set { _userId = value; }
        }
      }
    }


    XmlMessageModel:
    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// XmlMessage实体类(Product)
      /// </summary>
      public class XmlMessageModel : AbstractMessageModel
      {
        /**//// <summary>
        /// 构造函数
        /// </summary>
        public XmlMessageModel()
          : base()
        {
      
        }
      
        /**//// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="userId">UserId</param>
        /// <param name="msg">Message内容</param>
        /// <param name="pt">Message发布时间</param>
        public XmlMessageModel(string userId, string msg, DateTime pt)
          : base (msg, pt)
        {
          this._userId = userId;
        }
      
        private string _userId;
        /**//// <summary>
        /// Message内容
        /// </summary>
        public override string UserId
        {
          // 解密算法后的值
          get { return _userId; }
      
          // 加密算法后的值
          set { _userId = value; }
        }
      }
    }


    AbstractMessage:

    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// 操作Message抽象类(AbstractProduct)
      /// </summary>
      public abstract class AbstractMessage
      {
        /**//// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="amm">AbstractMessageModel</param>
        /// <returns></returns>
        public abstract string Insert(AbstractMessageModel amm);
      }
    }

    SqlMessage:

    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// Sql方式操作Message类(Product)
      /// </summary>
      public class SqlMessage : AbstractMessage
      {
        /**//// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="amm">AbstractMessageModel</param>
        /// <returns></returns>
        public override string Insert(AbstractMessageModel amm)
        {
          return "Sql方式插入Message。帐号:" + amm.UserId
            + ";内容:" + amm.Message
            + ";时间:" + amm.PublishTime.ToString();
        }
      }
    }

    XmlMessage

    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// Xml方式操作Message类(Product)
      /// </summary>
      public class XmlMessage : AbstractMessage
      {
        /**//// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="amm">AbstractMessageModel</param>
        /// <returns></returns>
        public override string Insert(AbstractMessageModel amm)
        {
          return "Xml方式插入Message。帐号:" + amm.UserId
            + ";内容:" + amm.Message
            + ";时间:" + amm.PublishTime.ToString();
        }
      }
    }

    AbstractMessageFactory

    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// 抽象Message工厂(AbstractFactory)
      /// </summary>
      public abstract class AbstractMessageFactory
      {
        /**//// <summary>
        /// 创建MessageModel对象
        /// </summary>
        /// <returns></returns>
        public abstract AbstractMessageModel CreateMessageModel();
      
        /**//// <summary>
        /// 创建Message对象
        /// </summary>
        /// <returns></returns>
        public abstract AbstractMessage CreateMessage();
      }
    }


    SqlMessageFactory

    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// SqlMessage工厂(ConcreteFactory)
      /// </summary>
      public class SqlMessageFactory : AbstractMessageFactory
      {
        /**//// <summary>
        /// 创建SqlMessageModel对象
        /// </summary>
        /// <returns></returns>
        public override AbstractMessageModel CreateMessageModel()
        {
          return new SqlMessageModel();
        }
      
        /**//// <summary>
        /// 创建SqlMessage对象
        /// </summary>
        /// <returns></returns>
        public override AbstractMessage CreateMessage()
        {
          return new SqlMessage();
        }
      }
    }

    XmlMessageFactory

    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// XmlMessage工厂(ConcreteFactory)
      /// </summary>
      public class XmlMessageFactory : AbstractMessageFactory
      {
        /**//// <summary>
        /// 创建XmlMessageModel对象
        /// </summary>
        /// <returns></returns>
        public override AbstractMessageModel CreateMessageModel()
        {
          return new XmlMessageModel();
        }
      
        /**//// <summary>
        /// 创建XmlMessage对象
        /// </summary>
        /// <returns></returns>
        public override AbstractMessage CreateMessage()
        {
          return new XmlMessage();
        }
      }
    }

    Message

    using System;
    using System.Collections.Generic;
    using System.Text;
      
    namespace Pattern.AbstractFactory
    {
      /**//// <summary>
      /// Context类
      /// </summary>
      public class Message
      {
        private AbstractMessage _insertMessage;
        private AbstractMessageModel _messageModel;
      
        /**//// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="factory">AbstractMessageFactory</param>
        public Message(AbstractMessageFactory factory)
        {
          DateTime pt = DateTime.Now;
      
          _insertMessage = factory.CreateMessage();
          _messageModel = factory.CreateMessageModel();
      
        }
      
        /**//// <summary>
        /// 插入Message
        /// </summary>
        /// <param name="userId">UserId</param>
        /// <param name="msg">Message内容</param>
        /// <param name="pt">Message发布时间</param>
        /// <returns></returns>
        public string Insert(string userId, string msg, DateTime pt)
        {
          _messageModel.UserId = userId;
          _messageModel.Message = msg;
          _messageModel.PublishTime = pt;
      
          return _insertMessage.Insert(_messageModel);
        }
      }
    }

    client

    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
      
    using Pattern.AbstractFactory;
      
    public partial class AbstractFactory : System.Web.UI.Page
    {
      protected void Page_Load(object sender, EventArgs e)
      {
        AbstractMessageFactory amf = new SqlMessageFactory();
      
        Message m = new Message(amf);
      
        Response.Write(m.Insert("admin", "Sql方式", DateTime.Now));
        Response.Write("<br />");
      
        amf = new XmlMessageFactory();
      
        m = new Message(amf);
      
        Response.Write(m.Insert("user", "Xml方式", DateTime.Now));
      }
    }

      运行结果

      Sql方式插入Message。帐号:admin;内容:Sql方式;时间:2007-5-3 22:04:56

      Xml方式插入Message。帐号:user;内容:Xml方式;时间:2007-5-3 22:04:56

      参考

      http://www.dofactory.com/Patterns/PatternAbstract.aspx



     C#设计模式(一)---简单工厂模式(Simple Factory Pattern) || 工厂方法模式(Factory Method)

          简单工厂模式,在OO程序设计中经常会在不知不觉中应用到一种模式就是简单工厂模式(Simple Factory Pattern)。根据提供给它的数据,返回几个可能类中的一个类的实例。这便是简单工厂模式从OO思想上的基本概念。继续前面概念的说明:通常情况下,它返回的实例的类都有一个共同的父类和共同的方法,但各自方法执行的任务不同,而且根据不同的数据进行了优化。简单工厂模式不属于23个GoF模式。

     简单工厂模式又叫静态工厂模式,顾名思义,它是用来实例化目标类的静态类。下面我主要通过一个简单的实例说明简单工厂及其优点。

        简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

    下面我们来看下具体的实例:

    我们使用一个计算器的实例来看

    ①创建运算父类:

    class Operation
        {
            double numberA;
            double numberB;

            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;
            }
        }

    ②继承父类, 实现 GetResult()方法:

     //sum
        class OperationAdd : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA + NumberB;
                return result;
            }       
        }
        //sub
        class OperationSub : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA - NumberB;
                return result;
            }
        }
        //Mul
        class OperationMul : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA * NumberB;
                return result;
            }
        }
        //Div
        class OperationDiv : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                if (NumberB==0)
                {
                    throw new Exception("NumberB is Zero");
                }
                result = NumberA / NumberB;
                return result;
            }
        }
    ③现在我们有个4个类实现了运算的方法,需要调用时只要创建他的实例就可以直接使用了 ,

    可是那样是很麻烦的,可是到底实例化那个对象呢?将来会不会增加实例化的对象呢?

    --------举例说明、比如增加平方根算法、在②和③中改动就可以了...

    所以我们使用一个单独的类,来实现专门的实例化,也就是我们今天要说的工厂类---以传入的参数(struing operation)来判断 该执行②中的哪个方法,也就是说实例化什么样的。。。

    class OperationFactory
        {
            public static Operation CreateOperate(string operation)
            {

                Operation oper = null;
                switch (operation)
                {
                    case "+":
                        oper = new OperationAdd();
                        break;
                    case "-":
                        oper = new OperationSub();
                        break;
                    case "*":
                        oper = new OperationMul();
                        break;
                    case "/":
                        oper = new OperationDiv();
                        break;
                }
                return oper;
            }
        }


    //托三个textbox以及combox,button

     private void button1_Click(object sender, EventArgs e)
            {
                Operation oper = OperationFactory.CreateOperate(comboBox1.Text);
                oper.NumberA = Convert.ToDouble(textBox1.Text);
                oper.NumberB = Convert.ToDouble(textBox2.Text);

                double result = oper.GetResult();
                textBox3.Text = result.ToString();
            }


    这样使用一个工厂类,只需要把参数传进去就可以实现具体的实例化,产生合适的对象,通过多态返回父类的方式实现结果。

    工厂方法模式

    定义一个用于创建对象的接口,让子雷决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类[DP]。

    代码:

     /// <summary>
        /// 运算类
        /// </summary>
        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; }
            }

            /// <summary>
            /// 得到运算结果
            /// </summary>
            /// <returns></returns>
            public virtual double GetResult()
            {
                double result = 0;
                return result;
            }
        }

        /// <summary>
        /// 加法类
        /// </summary>
        class OperationAdd : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA + NumberB;
                return result;
            }
        }

        /// <summary>
        /// 减法类
        /// </summary>
        class OperationSub : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA - NumberB;
                return result;
            }
        }
        /// <summary>
        /// 乘法类
        /// </summary>
        class OperationMul : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA * NumberB;
                return result;
            }
        }
        /// <summary>
        /// 除法类
        /// </summary>
        class OperationDiv : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                if (NumberB == 0)
                    throw new Exception("除数不能为0。");
                result = NumberA / NumberB;
                return result;
            }
        }

        /// <summary>
        /// 工厂方法
        /// </summary>
        interface IFactory
        {
            Operation CreateOperation();
        }

        /// <summary>
        /// 专门负责生产“+”的工厂
        /// </summary>
        class AddFactory : IFactory
        {
            public Operation CreateOperation()
            {
                return new OperationAdd();
            }
        }

        /// <summary>
        /// 专门负责生产“-”的工厂
        /// </summary>
        class SubFactory : IFactory
        {
            public Operation CreateOperation()
            {
                return new OperationSub();
            }
        }

        /// <summary>
        /// 专门负责生产“*”的工厂
        /// </summary>
        class MulFactory : IFactory
        {
            public Operation CreateOperation()
            {
                return new OperationMul();
            }
        }

        /// <summary>
        /// 专门负责生产“/”的工厂
        /// </summary>
        class DivFactory : IFactory
        {
            public Operation CreateOperation()
            {
                return new OperationDiv();
            }
        }

    客户端:

    static void Main(string[] args)
            {
                IFactory operFactory = new AddFactory();
                Operation oper = operFactory.CreateOperation();
                oper.NumberA = 1;
                oper.NumberB = 2;
                double result=oper.GetResult();

                Console.WriteLine(result);

                Console.Read();
            }

    简单工厂模式和工厂方法模式区别


    这个工厂类与分支耦合,那么我就对它下手,根据依赖倒转原则,我们把工厂类仇隙那个出一个借口,这个借口只有一个方法,就好似创建抽象产品的工作方法。然后,所有的要生产具体类的工厂,就去实现这个借口,这样,一个简单工厂模式的工厂类,变成了一个工厂抽象借口和多个具体生成对象的工厂,于是我们要增加‘求 M数的N次方'的功能时,就不需要更改原有的工厂类了,只需要增加次功能的运算类和相应的工厂类就可以了。---这样整个工厂和产品体系其实都没有修改的变化,而只是扩展的变化,这就完全符合了开放—封闭原则的精神


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xue1234567890/archive/2009/05/19/4201753.aspx


     

  • 相关阅读:
    c#中子线程控制进度条的一个简单例子
    c#中WinForm的TextBox循环自动滚动示例
    c#中重定向windows控制台程序的输出信息
    c#中List <int[]>集合添加和查找元素
    LogExplore的一个详细操作手册
    ConsoleApplication也精彩,一个控制台进度条的示例。
    c#通过oledb获取excel文件表结构信息
    Dephi中获取webbrowser选取区域的html代码示例
    SQL2005中利用xml拆分字符串序列
    今天装上了php6```
  • 原文地址:https://www.cnblogs.com/GeneralXU/p/1545462.html
Copyright © 2011-2022 走看看