马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

C#抽象工厂模式学习

[复制链接]
查看4501 | 回复2 | 2013-1-9 17:12:36 | 显示全部楼层 |阅读模式
什么事抽象工厂?抽象工厂模式有几种方法实现?

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

2.代码示例
[C#] 纯文本查看 复制代码
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; 
  } 
} 




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

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



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

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

[C#] 纯文本查看 复制代码
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还不行??
[C#] 纯文本查看 复制代码
public class FruitFactory 
{ 
  public Orange MakeOrange() 
  { 
   return new Orange(); 
  } 
  public Apple MakeApple() 
  { 
   return new Apple(); 
  } 
} 


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

[C#] 纯文本查看 复制代码
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中好像需要一个,还等什么呢?实现吧。

[C#] 纯文本查看 复制代码
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创建对象。还等什么呢?

[C#] 纯文本查看 复制代码
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; 
  } 
} 


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

C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
chao2332601 | 2013-6-16 02:02:22 | 显示全部楼层
谢谢分享!!!
chao2332601 | 2013-6-16 05:00:52 | 显示全部楼层
谢谢分享!!!
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则