时间: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