设计模式之策略模式

本文是对 Head First设计模式 一书中策略模式的一个总结。

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

 接下来我们通过一个鸭子类(Duck)来分析此模式,先来看看这个Duck类的定义:

0a7d565859d1b2c43393c92467ba4bd4ebe.jpg

Duck是一个抽象类,MallardDuck(绿头鸭)和RedheadDuck(红头鸭)分别继承于Duck,假设所有鸭子都会叫(quack)和游泳(swim),因此在父类中实现了quack()和swim()这两个方法,但是每一种鸭子的外观是不相同的,因此display()在父类中定义为抽象方法,每个子类分别进行实现。

软件开发中有一个不变的真理:change,需求时刻都在改变。比如现在有个需求,要让鸭子飞起来,如何实现?第一个想到的办法就是在超类中增加一个fly()方法并实现,这样所有继承了Duck类的鸭子都可以飞起来了。

但现实情况是并非所有的鸭子都会飞,比如RubberDuck(橡皮鸭子)就不会飞,这样在父类中定义 fly()方法就不太合适了,不能强制让一个橡皮鸭子飞吧。这时会有人说那还不简单,在橡皮鸭子中将fly()方法进行覆盖,进行空实现,这种做法貌似可以解决这个问题,但是如果有更多类型的鸭子呢,这时你将不得不对每一种类型的鸭子进行考虑要不要覆盖fly()方法,而且万一某个飞行行为要改变你是不是得修改所有继承于Duck的子类中的fly()方法?

这时我们发现使用继承并不能很好的解决此问题,因为鸭子的行为在子类里不断地改变,并且让所有的子类都有这些行为是不恰当的。这时候我们的第一个设计原则该登场了:

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

这个设计原则可以通俗的这样理解:“把会变化的部分取出并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的其他部分”。这几乎是每个设计模式背后的精神所在。

对于我们的例子中,鸭子的飞行行为就是可变化之处,我们要做的就是分开鸭子中变化和不会变化的部分

fly()是变化的部分,我们将他分离出来(远离Duck),建立一个新类。这个新类如何设计呢?我们希望一切能有弹性,因此第二个设计原则登场了:

设计原则:针对接口编程,而不是针对实现编程。

我们定义一个飞行行为相关的接口:FlyBehavior, 来代表飞行行为,这样具体的飞行行为将由实现了FlyBehavior接口的类实现,这样就针对接口编程了。“针对接口编程”真正的意思是“针对超类型编程”,关键在于多态,可以更明确地说成“变量的类型声明应该是超类型”,通常是一个抽象类或接口。

331d37efee034ea391d6d2fbdae905a95e7.jpg

Duck类:

public abstract class Duck {

    FlyBehavior flyBehavior;

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    public void performFly(){
        flyBehavior.fly();
    }

    public void quack(){
        System.out.println("quack!");
    }

    public void swim(){
        System.out.println("swim");
    }

    public abstract void display();
}

FlyBehavior类:

public interface FlyBehavior {
    void fly();
}

FlyWithWings类:

public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I'm flying!!");
    }
}

FlyNoWay类:

public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I can't fly");
    }
}

MallardDuck类:

public class MallardDuck extends Duck {

    public MallardDuck() {
        this.flyBehavior = new FlyWithWings();
    }

    @Override
    public void display() {
        System.out.println("I'm MallardDuck!");
    }
}

Main类:

public class Main {
    public static void main(String[] args) {
        MallardDuck mallardDuck = new MallardDuck();
        mallardDuck.performFly();
        // 动态改变鸭子的飞行行为
        mallardDuck.setFlyBehavior(new FlyNoWay());
        mallardDuck.performFly();
    }
}

 

 

 

 

转载于:https://my.oschina.net/u/1040143/blog/2395996

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值