C#net工厂模式(转载)

时间:2013-10-10    作者:悬浮的青春    分类: .net相关


 

 

最近项目中看到了运用工厂模式的代码。感觉似乎最显而易见的优点就是省去了大量的判断,其他优点估计就是工厂模式的优点了,见下文

 

利用设计模式可以使我们的代码更灵活,更容易扩展,更容易维护。各种面向对象的程序设计语言都提供了基本相同的机制:比如类、继承、派生、多态等等。但是又有各自的特色,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

 

标签: net

WRITTEN BY

avatar