早就在看设计模式了,一直很零散。这次Alex组织设计模式系列FreeTalk真是大好的机会,正好系统学习一下,好好学习,天天向上^_^。 也没有笔记,讲的时候蛮有感觉的,把自己的理解赶快写下来,以后也好有地方查。
第一课是抽象方法,或者抽象工厂方法? 大概是这个名字吧。
- 一个简单的例子是人吃奶粉的例子
- class 奶粉
- {
- }
- class 婴儿奶粉:奶粉
- {
- }
- class 老人奶粉:奶粉
- {
- }
- class 人
- {
- private 奶粉=null;
- public virtual void 吃奶粉
- {
- this.奶粉= new 奶粉();
- ......
- }
- }
- 在使用设计模式之前我们要这么写代码:
- class 婴儿:人
- {
- public override void 吃奶粉()
- {
- this.奶粉=new 婴儿奶粉();
- ....
- }
- }
- class 老人:人
- {
- public override void 吃奶粉()
- {
- this.奶粉=new 老人奶粉();
- ....
- }
- }
- 这里 人 的子类 都要覆盖父类的 吃奶粉() 方法,而之所以修改,只是因为奶粉类型不一样。这样的修改会使 吃奶粉() 方法 中其他的逻辑 遭遇危险,导致不稳定。
- 抽象方法 模式就是要把这种不稳定的逻辑隔离开来 ,把创建不同类型奶粉的代码 隔离出来。
- 看看例子。
- 奶粉的类不改动,我们来改动人这个类。
- class 人
- {
- private 奶粉=null;
- protected virtual 奶粉 Create奶粉() //添加 传说中的工厂方法
- {
- return new 奶粉();
- }
- public virtual void 吃奶粉
- {
- this.奶粉= this Create奶粉(); // 修改这一句
- ......
- }
- }
- 婴儿的类可以这么写:
- class 婴儿:人
- {
- proteced override 奶粉 Create奶粉() // 注意这里只是覆盖了 Create奶粉方法,并没有改动 吃奶粉() 方法的逻辑, 有效 隔离了危险。
- {
- return new 婴儿奶粉();
- }
- }
- 老人 类可以这么写
- class 老人:人
- {
- proteced override 奶粉 Create奶粉()
- {
- return new 老人奶粉();
- }
- }
- 好了,就是最简单的工厂方法了。
- 再看另一种实现:
- 或许每种人的子类都要 重写 Create奶粉() 太麻烦吧,有时候 可以这样写:
- 奶粉的类保持不变,修改人的类:
- class 人
- {
- private 奶粉=null;
- protected virtual 奶粉 Create奶粉() //修传说中的工厂方法
- {
- if(this.GetType() is 婴儿)
- return new 婴儿奶粉();
- if(this.GetType() is 老人)
- return new 老人奶粉();
- ........
- return new 奶粉();
- }
- public virtual void 吃奶粉 //这个方法不变
- {
- this.奶粉= this.Create奶粉(); // 修改这一句
- ......
- }
- }
- 这样,婴儿类和老人类就不需要覆盖Create奶粉()方法了,是不是 很省事了,可这种方法有很大的局限性,就是 人这个类 必须 知道它所拥有的哪些子类。遇到新的类型就麻烦了.
- 再看另一种实现方法:
- 上面的两种方法都涉及到子类要覆盖 人类中的方法(Create奶粉() 方法 或者 吃奶粉()方法). 奶粉的种类变化,需要修改食用者的内容, 给食用者带来不必要的麻烦. 我们来一种更加彻底的隔离.
- 奶粉的类不变.
- 添加一个工厂类(Factory)
- class 奶粉Factory()
- {
- public static 奶粉 Create奶粉(Type type)
- {
- if(type is 婴儿)
- return new 婴儿奶粉();
- if(type is 老人)
- return new 老人奶粉();
- ........
- }
- }
- 人类 修改如下:
- class 人
- {
- private 奶粉=null;
- public virtual void 吃奶粉
- {
- this.奶粉= 奶粉Factory.Create奶粉( this.GetType() ); // 修改这一句
- ......
- }
- }
- 这下好了,从此以后再不用修改人这个类和它的子类了。而且可以保证,每一种不同的人都能吃到相应的奶粉了。
- 如果有新的人或需要新的奶粉时只需要在 奶粉Factory的 Create奶粉() 方法中添加即可。