设计模式_策略模式_HEAD_FIRST整理

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

没用设计模式之前的例子 :


所有的鸭子类都是继承 Duck 类,所有鸭子的行为都是又超类 Duck 实现,因为每种鸭子的样子是不用的,所以在超类 Duck 里面定义了一个抽象的 display(); 每个子类鸭子去实现自己的外观。


但是由于需求变化, 现在要在鸭子的行为里面加入飞行的行为,直接在超类 Duck 里加入了一个 fly() 行为,然而出现了严重的后果,在鸭子子类的鸭子也出现了飞行的行为,然而橡皮鸭子是不会飞行的,这是严重不允许的。


这时可能会想到,在橡皮鸭里把 fly(); 方法给覆盖掉,然后什么也不做,但是以后可能还会有诱饵鸭,既不会飞也不会叫,只能继续覆盖,显然这不是一个好主意。


接着尝试使用接口


然而这样做就会增加许多重复的代码,也不是一个好的注意。

由此可见,继承并不能很好的解决问题,因为鸭子的行为在子类里不断的改变,并且让所有的子类都又这些行为时不恰当的,使用 Flyable 和 Quackable接口一开始还不错,解决了问题,只有会飞的鸭子才去继承 Flyable 接口,但是 JAVA 接口不具有实现代码 ,所以继承接口无法达到代码的复用,这代表着无论何时你需要修改某个行为的时候,你必须向下追踪并在每一个实现此行为的类中去修改(比如某些鸭子的飞行行为发生了改变,用翅膀飞变成了用火箭筒飞,哈哈举个例子而已,或者飞行速度发生了变化,你就需要在某个鸭子子类中去单独的修改,一个还好说,多了就很蛋疼了,也有可能发生新的错误,这是就需要使用设计模式了,因为鸭子的行为时变化的,所以我们可以把着部分单独的抽出来,之后在给每个鸭子单独的组合上这些行为,这样当行为改变的时候我们就可以改动很小的地方来完成某些需求


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

换句话说,如果每次需求一来,都会使某方面的代码发生变化,就可以确定这部分代码需要抽出来,和那些稳定的代码做区分。总体来说就是,把会变化的部分抽取并封装起来,以便以后可以轻易的修改或扩充此部分,而不影响其他不需要变化的部分。


这里所提到的变化的部分是指 fly() 和 quack() 行为,现在,为了分开变化的部分和不变的部分,我们准备建立两组类(远离 Duck 类),一个是 fly 相关的,一个是 quack 相关的,每一组类将实现各自的动作,比如 有一个类是 “呱呱叫 ” 一个是 “吱吱叫”

上面提到了一点就是组合,我们想要能够制定某个行为道子类鸭子的实例,比如,我们要产生一个新的绿头鸭实例,并制定特定类型的飞行行为给他,那这样就可以设计为让鸭子的行为可以动态的改变,也就是说我们应该在子类鸭子类中包含设定行为的方法,这样就可以在“运行”的时候“动态的设定”绿头鸭的行为。

这里又可以引出一个设计原则 : 针对接口编程,而不是针对实现编程。

我们利用每个接口来代表每个行为,比方说,定义两个接口 FlyBehavior 和 QuackBehavior ,而每个行为类去实现其中一个对应的接口。所以这次鸭子类不会去实现飞行和叫的接口,而是又我们新定义的类(“呱呱叫 ”)去实现 FlyBehavior 和 QuackBehavior ,这就称为行为类,由行为类而不是鸭子类去实现行为类接口。

这种做法异于以往,以前的做法是,行为来自 Duck 超类的具体实现,或者是实现某个接口由子类自行实现,这两种做法都是依赖于实现,没办法更改行为(除非写更多的代码)

在新的设计中,鸭子的子类将使用接口( FlyBehavior 和 QuackBehavior )所表示的行为(也就是借助行为类实现行为接口),所以实际的实现不会被绑死在鸭子的子类中。(也就是,特定的具体行为,编写在了实现FlyBehavior 和 QuackBehavior的行为类中)


说了这么多,开始上代码

首先建立两个接口 FlyBehavior 和 QuackBehavior

public interface FlyBehaviorInter {

     void fly();
}
public interface QuackBehaviorInter {

    void quack();
}

然后在新建一些行为类,这里我建了两个飞行行为和两个叫的行为

飞行 行为类

public class FlyWithWings implements FlyBehaviorInter{
    @Override
    public void fly() {
        System.out.println("用翅膀飞");
    }
}
public class FlyNoWay implements FlyBehaviorInter{

    @Override
    public void fly() {
        System.out.println("不会飞");
    }
}

叫 行为类

public class QuackForGuaGua implements QuackBehaviorInter{
    @Override
    public void quack() {
        System.out.println("呱呱叫");
    }
}
public class QuackForZhiZhi implements QuackBehaviorInter{
    @Override
    public void quack() {
        System.out.println("吱吱叫");
    }
}

然后是 超类 Duck

public abstract class Duck {

    /**声明行为类型为接口类型 由子类去定义具体的引用*/
    protected FlyBehaviorInter flyBehaviorInter;
    protected QuackBehaviorInter quackBehaviorInter;

    /**抽象的外观方法*/
    abstract void dishPlay();


    /** 执行鸭子的行为 具体实现被分离又单独的行为类去实现*/
    protected void performFly(){
        flyBehaviorInter.fly();
    }

    protected void performQuack(){
        quackBehaviorInter.quack();

    }


    /** 动态改变鸭子的行为 */
    public void setFlyBehaviorInter(FlyBehaviorInter flyBehaviorInter) {
        this.flyBehaviorInter = flyBehaviorInter;
    }

    public void setQuackBehaviorInter(QuackBehaviorInter quackBehaviorInter) {
        this.quackBehaviorInter = quackBehaviorInter;
    }
}

接着写两个 鸭子类 进行测试

public class GreenHeadDuck extends Duck{

    public GreenHeadDuck(){
        flyBehaviorInter = new FlyWithWings();
        quackBehaviorInter = new QuackForGuaGua();

    }
    
    @Override
    void dishPlay() {

        System.out.println("我是绿头鸭");
    }
}
public class RubberDuck extends Duck{

    public RubberDuck(){
        flyBehaviorInter = new FlyNoWay();
        quackBehaviorInter = new QuackForZhiZhi();
    }

    @Override
    void dishPlay() {
        System.out.println("我是橡皮鸭");
    }
}

最后就是 main 函数了

public class Main {

    public static void main(String[] a){

        GreenHeadDuck greenHeadDuck = new GreenHeadDuck();
        greenHeadDuck.dishPlay();
        greenHeadDuck.performFly();
        greenHeadDuck.performQuack();


        RubberDuck rubberDuck = new RubberDuck();
        rubberDuck.dishPlay();
        rubberDuck.performFly();
        rubberDuck.performQuack();
    }
}

总共也就这么多了 大概整理了一下


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值