策略模式

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

2.案例分析
我们以一个案例为开始,我们有一个模拟鸭子游戏:SimUDuck,游戏中可能会有很多的鸭子,我们设计如下图所示的结构。
类图
假设现在有一个橡皮鸭子RubberDuck,让其继承Duck类,那么问题来了,橡皮鸭子会集成Duck类的fly方法,显然橡皮鸭是不会飞的,虽然我们可以覆盖RubberDuck类中的fly方法让其什么都不做,但是如果有很多类似于橡皮鸭的其它鸭中,这将造成代码的冗余和不简洁。
所以我们换一种设计结构,将fly和quack设计成接口,即
这里写图片描述
这样设计会出现另外一个问题,如果有许多Duck的子类的都要修改fly方法,那么工作量将是巨大的,以为我们没有做到代码的复用。
继承会让子类拥有不需要的方法,接口又无法达到代码的复用。
设计原则:找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起。
这个例子中,Duck类是相对不变的,变化的是fly和quack,所以我们修改设计结构如下:
这里写图片描述
设计原则:针对接口编程,而不是针对实现编程。
简单来说就是

FlyBehavior fly = new FlywithWings();

而不是

FlywithWings fly = new FlywithWings();

鸭子现在会将飞行和呱呱叫的动作“委托”别人处理,而不是使用定义在Duck类(或子类)内的呱呱叫和飞行算法。

3.具体实现
Duck类

package sxd.learn.dp;

public abstract class Duck {
    protected FlyBehavior flyBehavior;
    protected QuackBehavior quackBehavior;

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

    public void setQuackBehavior(QuackBehavior qb){
        this.quackBehavior = qb;
    }

    public abstract void display();

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

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

    public void swim(){
        System.out.println("All duck float,even decoys");
    }
}
package sxd.learn.dp;

public class MallardDuck extends Duck{

    public MallardDuck(){
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }

    @Override
    public void display() {
        // TODO Auto-generated method stub
        System.out.println("I'm a real mallard duck!");
    }

}

FlyBehavior接口

package sxd.learn.dp;

public interface FlyBehavior {
    public void fly();
}
package sxd.learn.dp;

public class FlyNoWay implements FlyBehavior{

    @Override
    public void fly() {
        // TODO Auto-generated method stub
        System.out.println("I can't fly!!");
    }

}
package sxd.learn.dp;

public class FlyWithWings implements FlyBehavior {

    @Override
    public void fly() {
        // TODO Auto-generated method stub
        System.out.println("I'm flying!!");
    }

}

QuackBehavior 接口

package sxd.learn.dp;

public interface QuackBehavior {
    public void quack();
}
package sxd.learn.dp;

public class Quack implements QuackBehavior{

    @Override
    public void quack() {
        // TODO Auto-generated method stub
        System.out.println("Quack");
    }

}
package sxd.learn.dp;

public class squeak implements QuackBehavior{

    @Override
    public void quack() {
        // TODO Auto-generated method stub
        System.out.println("Squeak");
    }

}
package sxd.learn.dp;

public class MuteQuack implements QuackBehavior{

    @Override
    public void quack() {
        // TODO Auto-generated method stub
        System.out.println("Slience");
    }

}

测试分析类

package sxd.learn.dp;

public class DuckSimulator {
    public static void main(String[] args){
        Duck mallard = new MallardDuck();
        mallard.performFly();
        mallard.performQuack();

        System.out.println("dynamic change behavior");
        mallard.setFlyBehavior(new FlyNoWay());
        mallard.setQuackBehavior(new MuteQuack());
        mallard.performFly();
        mallard.performQuack();
    }
}

测试结果
这里写图片描述

4.总结
“有一个”可能比“是一个”更好:每个鸭子都有一个FlyBehavion和一个QuackBehavior,而不是每个鸭子是一个…..。
当我们将两个类结合起来使用,这就是组合。
设计原则:多用组合,少用集成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值