C#抽象工厂模式实现

利用设计模式可以使我们的代码更灵活,更容易扩展,更容易维护。各种面向对象的程序设计语言都提供了基本相同的机制:比如类、继承、派生、多态等等。但是又有各自的特色,C# 中的反射机制便是一个很重要的工具,好好地利用就可以在实际中发挥很大的作用。
 
  我们来看一个例子:
 
  我的程序中有需要一系列的对象,比如apple,orange…, 要想利用他们,我们就必须在程序中根据用户要求,然后一个个调用 new 操作符来生成他们,这样客户程序就要知道相应的类的信息,生成的代码显然不够灵活。我们可以在代码中不利用具体的类,而只是说明我们需要什么,然后就能够得到我们想要的对象吗?
 
  哦,我们都看设计模式,听吧,很多人都在那里鼓吹他们是如何如何的棒,我们看看怎么样利用他们来解决问题。目标明确了,那我们看看哪个能够符合我们的要求。GoF的《设计模式》都看过吧,似懂非懂的看了一些,那我们看看能够不能够 上去呢?J 嗯,我们的程序考虑的是对象怎么创建的,创建型模式应该符合要求吧。然后我们浏览一下各模式的 意图 部分。呵呵,第一个好像就撞到彩了,抽象工厂,我们看看吧, 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类 ,至少 无需指定它们具体的类 符合我们的要求。
 
  我们的问题好像用不到这么复杂,只有orange,apple等等(应该就是product了),他们显然是一类的,都是fruit,我们只要一个生产水果的工厂就可以,左边的继承层次不要,只有一个FruitFactroy看看行不,先别管它正统不正统,实用就行。

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

  
  
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应该是怎么样呢?
   
   
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);
  这样看起来好多了,至少我客户代码中不要再写那么一长串的判断代码了。
 
  既然不要条件判断,传入的只有水果的名称,假如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;  } }
  经过这样的处理以后,增加新的水果的时候,我们不需要修改客户代码了,同时工厂的代码也不需要修改了。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值