• c#设计模式工厂模式


    http://www.cnblogs.com/guyuehuanhuan/archive/2011/01/31/1948119.html

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

      

     

     

     

     

  • 相关阅读:
    Delphi公用函数单元
    Delphi XE5 for Android (十一)
    Delphi XE5 for Android (十)
    Delphi XE5 for Android (九)
    Delphi XE5 for Android (八)
    Delphi XE5 for Android (七)
    Delphi XE5 for Android (五)
    Delphi XE5 for Android (四)
    Delphi XE5 for Android (三)
    Delphi XE5 for Android (二)
  • 原文地址:https://www.cnblogs.com/peterdys/p/2767128.html
Copyright © 2020-2023  润新知