Free Talk 设计模式 之一

来源:互联网 发布:外包美工主要干嘛 编辑:程序博客网 时间:2024/06/05 18:12

 

      早就在看设计模式了,一直很零散。这次Alex组织设计模式系列FreeTalk真是大好的机会,正好系统学习一下,好好学习,天天向上^_^。       也没有笔记,讲的时候蛮有感觉的,把自己的理解赶快写下来,以后也好有地方查。

 

第一课是抽象方法,或者抽象工厂方法? 大概是这个名字吧。

 

  1. 一个简单的例子是人吃奶粉的例子
  2. class 奶粉
  3. {
  4. }
  5. class 婴儿奶粉:奶粉
  6. {
  7. }
  8. class 老人奶粉:奶粉
  9. {
  10. }
  11. class  人
  12. {
  13.     private 奶粉=null;
  14.     public virtual void 吃奶粉
  15.     {
  16.         this.奶粉= new 奶粉();
  17.         ......
  18.     }
  19. }
  20. 在使用设计模式之前我们要这么写代码:
  21. class 婴儿:人
  22. {
  23.     public  override void 吃奶粉()
  24.     {
  25.         this.奶粉=new 婴儿奶粉();
  26.         ....
  27.     }
  28. }
  29. class 老人:人
  30. {
  31.     public  override void 吃奶粉()
  32.     {
  33.         this.奶粉=new 老人奶粉();
  34.         ....
  35.     }
  36. }
  37. 这里 人 的子类 都要覆盖父类的 吃奶粉() 方法,而之所以修改,只是因为奶粉类型不一样。这样的修改会使  吃奶粉() 方法 中其他的逻辑 遭遇危险,导致不稳定。 
  38. 抽象方法 模式就是要把这种不稳定的逻辑隔离开来 ,把创建不同类型奶粉的代码 隔离出来。 
  39. 看看例子。
  40. 奶粉的类不改动,我们来改动人这个类。
  41. class  人
  42. {
  43.     private 奶粉=null;
  44.     protected virtual 奶粉 Create奶粉()  //添加 传说中的工厂方法
  45.     {
  46.         return new 奶粉();
  47.     }
  48.     public virtual void 吃奶粉
  49.     {
  50.         this.奶粉= this Create奶粉(); // 修改这一句
  51.         ......
  52.     }
  53. }
  54. 婴儿的类可以这么写:
  55. class 婴儿:人
  56. {
  57.     proteced  override 奶粉 Create奶粉() // 注意这里只是覆盖了 Create奶粉方法,并没有改动  吃奶粉() 方法的逻辑, 有效 隔离了危险。
  58.     {
  59.         return new 婴儿奶粉();
  60.     }
  61. }
  62. 老人 类可以这么写 
  63. class 老人:人
  64. {
  65.     proteced  override 奶粉 Create奶粉() 
  66.     {
  67.         return new 老人奶粉();
  68.     }
  69. }
  70. 好了,就是最简单的工厂方法了。
  71. 再看另一种实现:
  72. 或许每种人的子类都要 重写 Create奶粉() 太麻烦吧,有时候 可以这样写:
  73. 奶粉的类保持不变,修改人的类:
  74. class  人
  75. {
  76.     private 奶粉=null;
  77.     protected virtual 奶粉 Create奶粉()  //修传说中的工厂方法
  78.     {
  79.         if(this.GetType() is 婴儿)
  80.             return new 婴儿奶粉();
  81.         if(this.GetType() is 老人)
  82.             return new 老人奶粉();
  83.         ........
  84.         return new 奶粉();
  85.     }
  86.     public virtual void 吃奶粉 //这个方法不变
  87.     {
  88.         this.奶粉= this.Create奶粉(); // 修改这一句
  89.         ......
  90.     }
  91. }
  92. 这样,婴儿类和老人类就不需要覆盖Create奶粉()方法了,是不是 很省事了,可这种方法有很大的局限性,就是 人这个类 必须 知道它所拥有的哪些子类。遇到新的类型就麻烦了.
  93. 再看另一种实现方法:
  94. 上面的两种方法都涉及到子类要覆盖 人类中的方法(Create奶粉() 方法 或者 吃奶粉()方法). 奶粉的种类变化,需要修改食用者的内容, 给食用者带来不必要的麻烦. 我们来一种更加彻底的隔离.
  95. 奶粉的类不变.
  96. 添加一个工厂类(Factory)
  97. class  奶粉Factory()
  98. {
  99.     public static 奶粉  Create奶粉(Type type)
  100.     {
  101.         if(type is 婴儿)
  102.             return new 婴儿奶粉();
  103.         if(type is 老人)
  104.             return new 老人奶粉();
  105.         ........
  106.     }
  107. }
  108. 人类 修改如下:
  109. class  人
  110. {
  111.     private 奶粉=null;
  112.     public virtual void 吃奶粉 
  113.     {
  114.         this.奶粉= 奶粉Factory.Create奶粉( this.GetType()  ); // 修改这一句
  115.         ......
  116.     }
  117. }
  118. 这下好了,从此以后再不用修改人这个类和它的子类了。而且可以保证,每一种不同的人都能吃到相应的奶粉了。
  119. 如果有新的人或需要新的奶粉时只需要在 奶粉Factory的 Create奶粉() 方法中添加即可。
原创粉丝点击