zoukankan      html  css  js  c++  java
  • 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;   
              }
    }
    

      

     

     

     

     

  • 相关阅读:
    django 一对多操作
    django 单表常用操作
    element-ui
    vue与后台交互之post用法
    pip换国内源
    TCP/UDP的理解
    进程/线程/协程的理解
    《手牵手带你走进python世界》系列四
    《手牵手带你走进python世界》系列五
    《手牵手带你走进python世界》系列三
  • 原文地址:https://www.cnblogs.com/peterdys/p/2767128.html
Copyright © 2011-2022 走看看