Design pattern学习笔记 – what and why?

来源:互联网 发布:12 fan club动作数据 编辑:程序博客网 时间:2024/06/08 11:16

Design pattern学习笔记 – what and why?

1. 为什么要学习和应用设计模式

    我们在设计过程中面临的问题有很多已经被前人解决过,设计模式是前人经验的总结,学习和应用设计模式是对前人经验的重用,有助于我们更好的解决眼前问题。

    Instead of code reuse, withpatterns you get experience reuse.

2. 问题引入--鸭塘模拟游戏

    话说你是一个游戏公司的程序猿,该公司有个经典的鸭子游戏一直卖的很好,我们来看看游戏的主角鸭子的类结构:

    

    随着其他游戏公司的发力,原有游戏的竞争力受到挑战,公司经过头脑风暴,决定给原有的游戏增加点新内容:要让鸭子能飞,任务落到你头上了。你怎么做?

    作为一个面向对象的程序员,你很自然的在超级鸭子Duck中增加了fly方法,每个子类都通过继承从父类自动获取了fly方法,从而具备了飞行能力。我们再看看现在的鸭子演化成什么样了。

    

    只在父类这一个地方都进行了修改,就满足了要求,正当你自我崇拜的劲儿还没有过去,参加joy china的公司副总怒不可遏的电话就打过来了:“怎么搞的?游戏中的橡皮鸭都能在屏幕上飞来飞去了!”

    你坐不住了,开始认真反思,原来并不是所有的鸭子都适合新加的这个fly特性。怎么处理?那边老板火冒三丈,时间紧迫,只有把所有不适合fly的鸭子全找出来,在子类中重载该fly方法,什么都不做了。(不再飞了)

    这显然不是一个好方法,因为你要找到每一个修改的子类,重载fly方法,一不小心就可能遗漏;另外的,这样做违背了继承的本意;更恐怖的,你以后会碰到更多类似情况,比如说不是所有的鸭子都会quack,那就要再进行类似工作了,烦透了,不是?

    回头看看存在的问题:

    a. 存在大量的代码复制

    b. 运行时期无法修改对象(鸭子)的行为

    c. 很难了解对象(鸭子)的所有行为

    d. 超级鸭子(父类)的变化,无意间影响到其他不希望被影响的具体鸭子(子类)

    应用接口怎么样?

    引入Flyable接口和Quackable 接口,来定义fly和quack特性,同时从超级鸭子中去掉quack和fly方法,哪种鸭子需要fly就实现fly接口,quack类似。那类图变成这个样子:

    

    以上这种结构避免了增加fly行为对其他子类的影响,但随之而来的问题是,同样的fly方法需要在每一个需要fly的子类中实现,没有做到代码复用。

3. 宣教篇--变化

    在软件的整个生命周期中,唯一不变的是“变化”,你要不停地应对可能出现的各种变化。

    依据你的经验,变化来自哪里?(客户需求、第三方产品、部署方式、商务和市场因素)

    第一个设计准则:识别应用中变化的部分,将它们分离出来。Identifythe aspects of your application that vary and separate them from what stays thesame.

    第二个设计准则:对接口编程。Program to aninterface, not an emplementation.

4. 问题深入--鸭塘模拟游戏的进化

    依据第一个设计准则,第一步找出变化的部分,quack和fly,因为不同的鸭子,该特性是不同的。第二步,封装这些不同,将fly和quack封装到不同的类中。

    依据第二个设计准则,我们希望对fly和quack的封装,对外暴露统一的接口;其他类使用fly和quack时,只需了解接口,无需关注具体实现。

    我们来看看进化后的鸭子:

    

    Duck3增加两个成员变量,flyBehavior和quackBehavior,用于封装不同的fly行为和quack行为;Duck3增加两个成员方法performQuack和performFly,根据运行期间持有的具体fly实现类(FlyWithWings或FlyNoWay),quack实现类(Quack, Sqeak, MuteQuack)执行fly和quack;set方法为Duck3提供运行期间改变行为的能力。

    QuackBehavior和FlyBehavior为quack和fly提供统一接口,具体实现类实现不同的quack和fly行为。

    具体的鸭子在构造器中获取具体的quack和fly实现。

    来看看代码:

    public abstract classDuck {

       FlyBehavior flyBehavior;

       QuackBehavior quackBehavior;

       public Duck(){         

       }

       public abstract void display();

       public void performFly(){

              flyBehavior.fly();

       }

       public void performQuack(){

              quackBehavior.quack();

       }

       public void swim(){

              //swiming and swiming

       }

    }    

    public interfaceFlyBehavior {

       public void fly();

    }

    public class FlyNoWayimplements FlyBehavior{

       public void fly() {    

       }

    }

    public classFlyWithWings implements FlyBehavior{

       public void fly() {           

       }

    }

    public classMallardDuck extends Duck{

       public MallardDuck(){

              quackBehavior = new Quack();

              flyBehavior = new FlyWithWings();

       }

 

       @Override

       public void display() {

       }

    }

    public classMiniDuckSimulator {

       public static void main(String[] args){

              Duck mallard = new MallardDuck();

              mallard.performFly();

              mallard.performQuack();

       }

    }

    我们实现了原来设定的目标:

    a. 鸭子不同的行为被封装起来(以fly为例,不同的fly被封装到统一的接口FlyBehavior中),在超级鸭子类中,引用该接口执行统一的fly方法;超级鸭子无需了解具体fly的实现,只知道fly接口。

    b. 实现代码复用。具体fly的实现和quack的实现只用出现在一处。

    c. 了解鸭子所有的行为很简单,只要累加超级鸭子的所有成员方法

    d. 通过超级鸭子的set方法,具备了运行期间改变行为的内容

    e. 新增一种行为的具体实现,只需增加具体的实现类即可,不影响其他已有实现

5. 宣教篇--组合

    第三个设计准则:组合优于继承。Favor compositionover inheritance.

    策略模式的定义:

    The Strategy Pattern definesa family of algorithms, encapsulates each one, and makes them interchangeable.Strategy lets the algorithm vary independently from clients that use it.

    策略模式定义了一组算法,封装每个算法的不同,对外提供统一方法,从而使得使用者注意不到每个算法的不同。

6. 其他

    为什么学习设计模式

    a. 在团队中学习和应用设计模式,有助于团队之间的高效沟通

    b. 基于设计模式的交流,能使彼此准确了解,减少误解

    c.  用设计模式的词汇进行沟通,就能让团队长久地把沟通定位在设计而不是时不时地陷入实现的细节

    d. 学习和应用设计模式,能促进团队的能力提升

    怎么应用设计模式

    a. 设计模式是思想,更高层的东西,没有类库、框架之类的东西可以用;只有深入内心,在深入理解和结合具体应用才能发现适合某种模式的场景,应用某种模式。

    b. 实际中发现没有适合的模式时,应该怎么处理?前人总结出来的设计模式不是我们唯一的工具,在学习过程中我们会学习很多面向对象的准则,恰当运用这些准则也能获得好的设计(其实大多数设计模式都是对面向对象准则的实现)。

    c. 了解面向对象的基本特征(抽象、封装、继承、多态)并不能保证你成为一个好的面向对象设计者,好的面向对象设计者要立志于设计高复用,可维护的,灵活应对变化的系统。

7. 总结

    OO basic

    abstraction,encapsulation, polymorphism, inheritance

    

    OO principles

    Encapsulate what varies.

    Favor composition overinheritance.

    Program to interfaces, notimplementation.

    

    OO patterns

    The Strategy Patterndefines a family of algorithms, encapsulates each one, and makes them interchangeable.Strategy lets the algorithm vary independently from clients that use it.

    

 

原创粉丝点击