• 【Head First 设计模式(中文版)-读书笔记】1.欢迎来到设计模式世界:设计模式入门


    Joe上班的公司做了一套模拟鸭子游戏:SimUDuck。游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。此系统的内部设计使用了标准的OO技术,设计了一个鸭子超类(Superclass),并让各种鸭子继承此超类。类图如下:

    去年,公司的竞争压力加剧,主管们确定,此模拟程序需要会飞的鸭子(第一次需求)来将竞争者抛在后头。Joe的想法和类图如下(使用继承+重写覆盖-方案1-1):

    但是,可怕的问题发生了,所有的鸭子都会飞,尝试用覆盖的方法去解决,但是每次加入一种新鸭子后,都要重写Duck类里的会改变的方法(例如,fly(),quack() ),达不到复用的目的。

    利用继承来提供Duck的行为,这会导致A.代码在多个子类中重复,B.运行时的行为不容易改变,C.很难知道所有鸭子的全部行为。D.改变会牵一发动全身,造成其他鸭子不想要的改变。

    方案1-2(利用接口):

    但是问题又来了:

    我们知道,并非“所有”的子类都具有飞行和呱呱叫的行为,所以继承并不是适当的解决方式。虽然Flyable与Quackable可以解决“一部分”问题(不会再有会飞的橡皮鸭),但是却造成了代码无法复用,这只能算是从一个恶梦跳进另一个恶梦。甚至,在会飞的鸭子中,飞行的动作可能还有多种变化……

    方案1-3:

    如果每次新的需求一来,都会使某方面的代码发生变化,那么你就可以确定,这部分的代码需要被抽出来,和其他稳定的代码有所区分。

    为了要分开“变化和不会变化的部分”,我们准备建立两组类(完全远离Duck类),一个是“fly”相关的,一个是“quack”相关的,每组类将实现各自的动作。比方说,我们可能有一个类实现“呱呱叫”,另一个类实现“吱吱叫”,还有一个类实现“安静”。

    针对接口编程--针对超类型编程--变量的声明类型应该是超类型 (多态),类图和代码如下:

     1 //------飞行行为接口和实现类-------
     2 interface FlyBehavior {
     3     public void fly();
     4 }
     5 
     6 class FlyWithWings implements FlyBehavior {
     7     public void fly() {
     8         System.out.println("I'm flying");
     9     }
    10 }
    11 
    12 class FlyNoWay implements FlyBehavior {
    13     public void fly() {
    14         System.out.println("I can't fly");
    15     }
    16 }
    17 
    18 //---------叫声行为及实现类--------
    19 interface QuackBehavior {
    20     public void quack();
    21 }
    22 
    23 class Quack implements QuackBehavior {
    24     public void quack() {
    25         System.out.println("Quack");
    26     }
    27 }
    28 
    29 class Squeak implements QuackBehavior {
    30     public void quack() {
    31         System.out.println("Squeak");
    32     }
    33 }
    34 
    35 class MuteQuack implements QuackBehavior {
    36     public void quack() {
    37         System.out.println("Silence");
    38     }
    39 }
    40 //--------鸭子超类-------
    41 
    42 abstract class Duck {
    43     FlyBehavior flyBehavior;
    44     QuackBehavior quackBehavior;
    45 
    46     public Duck() {
    47 
    48     }
    49 
    50     public abstract void display();
    51 
    52     public void performFly() {
    53         flyBehavior.fly();
    54     }
    55 
    56     public void performQuack() {
    57         quackBehavior.quack();
    58     }
    59 
    60     public void swim() {
    61         System.out.println("All ducks float, even decoys");
    62     }
    63 }
    64 
    65 //-----绿头鸭类----------
    66 class MallardDuck extends Duck {
    67     public MallardDuck() {
    68         quackBehavior = new Quack();
    69         flyBehavior = new FlyWithWings();
    70     }
    71 
    72     public void display() {
    73         System.out.println("I'm a real Mallard duck");
    74     }
    75 }
    76 
    77 //------测试类--------------
    78 public class MiniDuckSimulator {
    79     public static void main(String[] args) {
    80         Duck mallardDuck = new MallardDuck();
    81         mallardDuck.performFly();
    82         mallardDuck.performQuack();
    83     }
    84 }
  • 相关阅读:
    powershell 更新 IIS SSL 证书
    让 .NET 轻松构建中间件模式代码(二)
    让 .NET 轻松构建中间件模式代码
    小白学数据分析----->学习注册转化率
    说说第三方服务
    小白学数据分析----->ARPPU的误区
    写在2013年最后一天
    小白学数据分析----->移动游戏的使用时长分析
    小白学数据分析----->付费用户生命周期研究
    小白学数据分析----->什么才是留存率的关键?
  • 原文地址:https://www.cnblogs.com/chenhongarticles/p/8526066.html
Copyright © 2020-2023  润新知