GitHub源码分享

微信搜寻:码农StayUp
主页地址:https://gozhuyinglong.github.io
源码分享:https://github.com/gozhuyinglong/blog-demos

1. 一个简略的模仿鸭子游戏

咱们先来看一个模仿鸭子的游戏:游戏中会呈现各种鸭子,它们一边游泳戏水,一边呱呱叫。

通过一番调研后:
已知的鸭子品种有:野鸭(Mallard Duck)、红头鸭(Redhead Duck)、橡皮鸭(Rubber Duck)。
已知的鸭子行为有:游泳(Swim)、嘎嘎叫(Quack)、显示鸭子的样子(Display)。

上面是这些鸭子的外观:

需要明确,开搞!

1.1 是时候展现OO技术了~

为了可复用性,设计了一个鸭子超类Duck,并让各种鸭子继承此超类:

  • 该超类中实现了swim()quack()办法,因为每一种鸭子外观不同,所以display()指定为形象办法(当然该类也是抽象类)。
  • 各个子类具体实现了display()办法
  • 因为橡皮鸭不会“嗄嗄叫”,所以重写了quack()办法为“吱吱叫”。

上面是UML类图:

1.2 Change!!!

咱们晓得软件开发的一个不变的真谛是:“变动”!

当初要求减少一种鸭子行为:航行(Fly),该怎么做呢?

如果持续应用继承,那么橡皮鸭是不会航行的,还是须要重写fly()办法。如下:

那如果再减少一种鸭子:钓饵鸭(Decoy Duck),这是只木头鸭子,它即不会叫,也不会航行......

看来继承是不能满足需要了!

1.3 应用接口怎么样?

fly()办法和quack()抽离进去,做成接口,让领有该行为的鸭子对其进行实现。如下:

这仿佛解决了当初的问题!

但如果再减少100只鸭子呢?岂不是所有会航行或会叫的鸭子,都要实现一遍,没有达到代码的复用性。而且一旦要批改某个行为将是一件苦楚的事(比方将所有“吱吱叫”改成“仿真呱呱叫”)……

1.4 封装变动

有一个设计准则,恰好实用于下面模仿鸭子游戏的情况。

找出利用中可能须要变动之处,把它们独立进去,不要和那些不须要变动的代码混在一起。

换句话说,如果每次来新的需要,都会使某方面的代码发生变化,那么你就能够确定,这部分的代码须要被抽出来,和其余稳固的代码有所辨别。

这便是策略模式的精力所在,上面咱们来看该模式的具体介绍。

2. 策略模式

策略模式(Strategy Pattern)是一种行为型模式。该模式定义一系列的算法,把它们一个个封装起来,并使它们能够互相替换。该模式让算法的变动独立于应用它的客户。

Define a family of algorithms, encapsulate each one, and make them interchangeable.

该设计模式体现了几个设计准则:

  • 封装变动
  • 针对接口编程,而不是实现类
  • 多用组合,少用继承

策略模式由三局部组成:

  • Strategy(策略)

定义了所有策略的公共接口。上下文(Context)应用这个接口来调用某个具体策略(ConcreteStrategy)。

  • ConcreteStrategy(具体策略)

Strategy接口的实现,定义了一个具体的策略实现。

  • Context(上下文)

定义了Strategy对象如何来应用,是策略算法的调用者。

3. 代码实现

咱们应用策略模式实现下面模仿鸭子游戏。

3.1 航行行为实现

定义航行行为接口

public interface Fly {    void fly();}

用翅膀航行实现类

public class FlyWithWings implements Fly {    @Override    public void fly() {        System.out.println("用翅膀航行");    }}

不会航行实现类

public class FlyNoWay implements Fly {    @Override    public void fly() {        System.out.println("不会航行");    }}

3.2 鸭叫行为实现

定义鸭叫行为接口

public interface Quack {    void quack();}

呱呱叫实现类

public class QuackGuaGua implements Quack {    @Override    public void quack() {        System.out.println("呱呱叫");    }}

吱吱叫实现类

public class QuackZhiZhi implements Quack {    @Override    public void quack() {        System.out.println("吱吱叫");    }}

不会叫实现类

public class QuackNoWay implements Quack {    @Override    public void quack() {        System.out.println("不会叫");    }}

3.3 鸭子类的实现

定义鸭子抽象类

public abstract class Duck {    protected Fly fly;    protected Quack quack;    public void swim() {        System.out.println("正在游泳...");    }    public abstract void display();    public Fly getFly() {        return fly;    }    public Quack getQuack() {        return quack;    }}

野鸭实现类

public class MallardDuck extends Duck {    // 野鸭用翅膀航行,呱呱叫    public MallardDuck() {        this.fly = new FlyWithWings();        this.quack = new QuackGuaGua();    }    @Override    public void display() {        System.out.println("外观是绿头鸭");    }}

红头鸭实现类

public class RedheadDuck extends Duck {    // 红头鸭用翅膀航行,呱呱叫    public RedheadDuck() {        this.fly = new FlyWithWings();        this.quack = new QuackGuaGua();    }    @Override    public void display() {        System.out.println("外观是红头鸭");    }}

橡皮鸭实现类

public class RubberDuck extends Duck {    // 橡皮鸭不会航行,吱吱叫    public RubberDuck() {        this.fly = new FlyNoWay();        this.quack = new QuackZhiZhi();    }    @Override    public void display() {        System.out.println("外观是橡皮鸭");    }}

钓饵鸭实现类

public class DecoyDuck extends Duck {    // 钓饵鸭不会航行,也不会叫    public DecoyDuck() {        this.fly = new FlyNoWay();        this.quack = new QuackNoWay();    }    @Override    public void display() {        System.out.println("外观是钓饵鸭");    }}

3.4 测试

编写简略测试类

public class Test {    public static void main(String[] args) {        MallardDuck mallardDuck = new MallardDuck();        mallardDuck.display();        mallardDuck.swim();        mallardDuck.getFly().fly();        mallardDuck.getQuack().quack();        System.out.println("-------------------");        DecoyDuck decoyDuck = new DecoyDuck();        decoyDuck.display();        decoyDuck.swim();        decoyDuck.getFly().fly();        decoyDuck.getQuack().quack();    }}

输入后果

外观是绿头鸭正在游泳...用翅膀航行呱呱叫-------------------外观是钓饵鸭正在游泳...不会航行不会叫

4. 残缺代码

残缺代码请拜访我的Github,若对你有帮忙,欢送给个Star,谢谢!

https://github.com/gozhuyingl...

5. 参考

  • 《 Head First 设计模式 》
  • 《 设计模式:可复用面向对象软件的根底 》

举荐浏览

  • 单例模式