策略模式学习

定义

策略模式定义了一系列算法,将每个算法封装起来,并且使他们之间可以相互替换,策略算法让算法的变化不会影响到使用算法的客户。策略模式类图见下图:
这里写图片描述
(1)Strateegy:定义了一个共同的接口。所有的具体算法类实现这个接口。环境(上下文)使用这个接口调用具体的算法类。
(2)ContrConcreteStrategy:封装了具体的算法,实现了一个接口。
(3)Context:环境(上下文类)。用于配置一个具体的算法策略对象,维持一个策略接口类型的参考,并且可以定义一个让接口Strategy的具体对象方位的接口。简单情况下,context类可以省略。

案例

鸭子应用(headfirst设计模式copy过来)
JOE做了一套成功的模拟鸭子游戏:SimUDuck,游戏中出现各种鸭子,一边游戏戏水,一边呱呱叫,设计了一个鸭子超类,让各种鸭子继承此超类。
这里写图片描述
现在要加一个鸭子飞的功能:在超类duck中加入fly的方法,让其他子类继承来实现功能。
这里写图片描述
但是,这样的话会出现一个问题,并不是所有的鸭子都会飞,如橡皮鸭。若在子类中重写飞的方法,变成什么都不做,再来一个诱饵鸭,不会飞也不会叫,再在诱饵鸭中覆盖掉叫和飞的方法。
利用继承提供duck的行为,导致缺点有以下几点:

  • 代码在多个子类中重复
  • 运行时的行为不易改变
  • 难以得知所有鸭子的全部行为
  • 改变牵一发动全身,造成其他鸭子不想要的改变

改进,建立飞行和叫的接口,让会飞的实现飞行的接口,会叫的实现叫的接口
这里写图片描述
上面的继承方式和接口方式的缺点:

  • 继承方式,改变鸭子的行为会影响所哟种类的鸭子,不恰当
  • 接口方式:Java接口不具有实现代码,继承接口无法达到代码的复用

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

分开变化和不变化的东西,建立两组类一个是fly相关的,一个是quack相关的,每一组类将实现各自的动作
这里写图片描述

设计原则:针对接口编程,而不是针对实现编程
我们希望一切有弹性,毕竟正是因为一开始鸭子的行为没有弹性,才开始这样的设计,指定行为到鸭子实例。应该在鸭子类中包含设定行为的方法。就可以在运行时动态改变鸭子的行为。利用接口代表行为,行为的每个实现都必须实现这些接口之一
这里写图片描述

设计原则:多用组合,少用继承
在模拟鸭子的例子中,鸭子的行为不是继承而来,而是和适当的行为对象组合而来,“有一个”可能比“是一个”更好

代码实现

public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;    
    public Duck(){

    }   
    public abstract void display();
    //委托给行为类
    public void performFly(){
        flyBehavior.performFly();
    }

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

    public void swim() {
        System.out.println("All ducks float, even decoys!");
    }
}
public class MallardDuck extends Duck{
    public MallardDuck() {
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }

    @Override
    public void display() {
        System.out.println("I'm a real Mallard duck");
    }
}

//飞行行为的接口
public interface FlyBehavior {
    public void performFly();
}
public class FlyWithWings implements FlyBehavior{
    @Override
    public void performFly() {
        System.out.println("I'm flying!!");
    }
}

//叫的行为接口
public interface QuackBehavior {
    public void performQuack();
}
public class Quack implements QuackBehavior {
    @Override
    public void performQuack() {
        System.out.println("Quack");
    }
}
//测试类
public class MiniDuckSimulator {
    public static void main(String[] args) {
        Duck mallard = new MallardDuck();
        mallard.performFly();
        mallard.performQuack();
    }
}

动态给鸭子设定行为,而不是在鸭子的构造器内实例化。在duck类中加两个方法,实现动态指定其行为

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

public void setQuackBehavior(QuackBehavior quackBehavior){
    this.quackBehavior = quackBehavior;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值