zoukankan      html  css  js  c++  java
  • HeadFirst学习笔记-1. 设计模式入门(转载)

    原文地址

    https://www.cnblogs.com/liang24/p/10440467.html

    1.概念

    在开始学习前,我们先了解一些概念,方便我们接下来的学习。

    OO基础

    • 抽象

    • 继承

    • 多态

    • 封装

    OO原则

    • 封装变化

    • 多用组合,少用继承

    • 针对接口编程,不针对实现编程

    设计模式

    设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
    使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 -- 来自百度百科

    2.案例

    我们从一个案例项目开始我们的学习之旅。

    项目背景

    Joe上班的公司做了一套相当成功的模拟鸭子游戏:SimUDuck。游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。此系统的内部设计使用了标准的OO技术,设计一个鸭子超类,并让各种鸭子继承此超类。
    根据项目需求,设计项目结构,如下图:

    新需求

    现在我们得让鸭子能飞,怎么办?
    最直接的办法就是在超类里添加Fly行为,因此Joe在Duck类里增加了Fly行为。如下图:

     

    出问题了

    但是,可怕的问题发生了...游戏里出现了很多会飞的“橡皮鸭”,这与现实不符。为什么会出现这个问题?
    原来Joe忽略了一件事情:并非所有的Duck子类都会飞。Joe在Duck父类中加上新的行为,会使得某些并适合该行为的子类也具有该行为。
    注:不要轻易在父类中添加行为或属性。

     

    使用继承?

    Joe想到了继承,把橡皮鸭类中的Fly行为覆盖掉。如果以后增加木头鸭(WoodDuck),又会怎样呢?木头鸭不会叫,又不会飞。。。
    使用继承的话,很容易出现需要对大量的子类进行修改。

    使用接口?

    Joe把Fly()从父类中取出来,定义一个“Flyable”接口,只有会飞的鸭子才实现此接口,同样的,也设计一个“Quackable"接口,因此也不是所有鸭子会叫。如下图:

    这样一来,重复的代码更多了,假如你要修改48个Duck子类的Fly()行为,会崩溃的。如果你是Joe,你会怎么办?

     

     

    不变的是变化

    面对上面的问题,有一个设计原则适用于此状况:

    封装变化:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

    分开变化和不会变化的部分

    从哪里开始呢?就我们目前所知,除了Fly()和Quack()的问题之外,Duck类还算一切正常,为了要分开“变化和不会变化的部分”,我们准备建立两组类(完全远离Duck类),一个是“Fly”相关的,一个是“Quack”相关的,每一组类将实现各自的动作。

     

     

     

    设计鸭子的行为

    如何设计那组实现Fly和Quack的行为的类呢?
    我们希望一切能有弹性,毕竟,正是因为一开始鸭子行为没有弹性,才让我们走上现在这条路。还想能够“指定”行为到鸭子的实例。

    为了满足以上目标,第二个设计原则适用于此状况:

    针对接口编程,而不是针对实现编程。

    我们利用接口代表每个行为,比方说,FlyBehavior与QuackBehavior,而行为的每个实现都将实现其中的一个接口。

     

    实现鸭子的行为

    在此,我们有两个接口,FlyBehavior和QuackBehavior,还有它们对应的类,负责实现具体的行为:

     

    这样的设计,可以让Fly和Quack的动作被其他的对象复用,因为这些行为已经与鸭子类无关了。
    而我们可以新增一些行为,不会影响到既有的行为类,也不会影响“使用”到Fly行为的鸭子类。

    整合鸭子的行为

    关键在于,鸭子现在会将飞行和呱呱叫的动作“委托”(delegate)别人自理,而不是使用定义在Duck类(或子类)内的呱呱叫和飞行方法。
    1、首先,在Duck类中“加入两个实例变量”,分别为“flyBehavior”和“quackBehavior”。
    2、实现performFly()和performQuack()
    3、初始化实例变量“flyBehavior”和“quackBehavior”。

    “有一个”可能比“是一个”更好

    这是一个很重要的技巧。其实是使用了我们的第三个设计原则:

    多用组合,少用继承。

    动态设置行为

    通过setter来设定鸭子的行为,而不是在构造器内实例化。

    public void SetFlyBehavior(flyBehaivor fb){
        flyBehaivor = fb;
    }
    
    public void SetQuackBehavior(flyBehaivor qb){
        quackBehaivor = qb;
    }
     

    整体结构

     

    3.总结

    案例中使用了第一个设计模式:策略模式(Strategy Pattern)

    策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

    策略模式结构图:

     

     
  • 相关阅读:
    什么是软件质量?
    软件生存周期及其模型是什么?
    给你一个网站,你如何测试?
    jquery中$.get()提交和$.post()提交有区别吗?
    JQuery有几种选择器?
    ajax和layui总结
    md5加密
    Collection接口相关介绍
    JS 中document.URL 和 windows.location.href 的区别
    window.location.href的用法(动态输出跳转)
  • 原文地址:https://www.cnblogs.com/zhboke/p/14233684.html
Copyright © 2011-2022 走看看