HeadFirst设计模式学习--策略模式

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

使用设计模式最好的方式是:把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们。以经验复用代替代码复用!

书中例子:
有一套模拟鸭子的游戏。游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。游戏采用了标准OO技术,设计了一个鸭子超类SuperClass,并让各种鸭子继承此超类。
现在需要为鸭子添加新的行为Fly。如果在SuperClass中添加Fly则会使所有的鸭子对象都具有该方法。但实际中有些鸭子(例如橡皮鸭)是不会飞的。这种情况下只能在橡皮鸭子类中覆盖Fly。这无疑比较丑陋。

到这里其实最直观的想法是:任其继承,我们只需要根据不同的鸭子类型进行覆盖即可,不会飞的鸭子Fly中就什么事都不做,但是这样做会有什么问题呢?

利用继承来提供Duck的行为,这会导致下列哪些缺点?

  1. 代码在多个子类中重复
  2. 运行时行为不容易改变
  3. 很难知道所有鸭子的行为
  4. 改变会牵一发而动全身,造成其他鸭子不想要的改变

其实最容易想到的可怕结果就是,利用继承的话,后续只要有一个新的Duck子类被创建,就要检查是否需要覆盖Fly方法,而在实际开发中,不断更新是很正常的需求,简直是无穷无尽的噩梦! 同时,原文中鸭子呱呱叫的方法也不尽相同,可以想象出无谓的的工作量。

那么如果利用接口呢?

每个会飞的子类都需要实现Fly接口,会出现大量重复代码,没有做到代码复用。和使用继承的方法差不多,都需要很多额外的工作量!

那到底应该怎么解决呢?现在先让我们看下面两个设计原则:

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

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

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

第二条原则的意思是,利用接口代替每个行为,而行为的每个实现都将实现其中的一个接口。这里需要注意,与上述讨论的利用接口解决问题思路是不同的,之前的做法是具体的鸭子子类去实现接口,而现在是专门用一些“行为”类去实现这些接口。因此,鸭子的子类将使用接口所表示的行为,所以实际的“实现”不会被绑死鸭子的子类中。

喵

 这样的设计,可以让飞行和呱呱叫的动作被其他对象复用,因为这些行为已经与鸭子类无关了。同时,也可以根据实际新增一些行为,不会影响到既有的行为类,也不会影响“使用”飞行行为的鸭子类。

下面附上代码:

/**
 * @author Beat IT
 * <p>
 * created 2020/7/3 3:19 下午
 */
public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck(){
    }

    public abstract void display();

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

    public void performQuack(){
        quackBehavior.quack();
    }

    public void setFlyBehavior(FlyBehavior newFlyBehavior){
        flyBehavior = newFlyBehavior;
    }

    public void setQuackBehavior(QuackBehavior newQuackBehavior){
        quackBehavior = newQuackBehavior;
    }
}
/**
 * @author Beat IT
 * <p>
 * created 2020/7/3 3:19 下午
 */
public interface FlyBehavior {
    void fly();
}
/**
 * @author Beat IT
 * <p>
 * created 2020/7/3 3:23 下午
 */
public class FlyWithWings implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("I'm flying!");
    }
}
/**
 * @author Beat IT 
 * <p>
 * created 2020/7/3 3:24 下午
 */
public class FlyNoWay implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("I can't fly!");
    }
}

/**
 * @author Beat IT
 * <p>
 * created 2020/7/3 3:20 下午
 */
public interface QuackBehavior {
    void quack();
}
/**
 * @author Beat IT
 * <p>
 * created 2020/7/3 3:26 下午
 */
public class Quack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Quack!");
    }
}

/**
 * @author Beat IT
 * <p>
 * created 2020/7/3 3:26 下午
 */
public class MuteQuqak implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Silence");
    }
}
/**
 * @author Beat IT
 * <p>
 * created 2020/7/3 3:27 下午
 */
public class Squack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Squack!");
    }
}
/**
 * @author Beat IT
 * <p>
 * created 2020/7/3 3:31 下午
 */
public class MallardDuck extends Duck{

    @Override
    public void display() {
        System.out.println("I'm a real MallarDuck!");
    }
}
/**
 * @author Beat IT
 * <p>
 * created 2020/7/3 3:33 下午
 */
public class DuckTest {
    public static void main(String[] args) {
        MallardDuck mallardDuck = new MallardDuck();
        mallardDuck.setFlyBehavior(new FlyWithWings());
        mallardDuck.setQuackBehavior(new Quack());
        mallardDuck.performFly();
        mallardDuck.performQuack();
    }
}

这就是策略模式,但是个人来说看完书上的讲解还是有点费解,先放上来,后续想通再做更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值