01策略模式

策略模式(strategy pattern)定义

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

分开变化和不会变化的部分

Duck类内的fly()和quack()行为会随着鸭子的不同而改变,属于变化的部分,将它们从Duck中抽取出来,建立一组新类代表每一种行为。

设计鸭子的行为

  • 以往:行为来自于继承Duck超类的具体实现,或是继承某个接口后由子类自行实现而来。这两种方法都依赖于实现,没办法改变行为。

  • 现在:Duck的子类将使用接口(FlyBehaviorQuackBehavior)所表示的行为,所以实际的“实现”不会被绑死在鸭子的子类中。

  • FlyBehavior

    public interface FlyBehavior {
        abstract void fly();
    }
    
  • QuackBehavior

    public interface QuackBehavior {
        void quack();
    }
    

实现鸭子的行为

  • 我们已经有了2个行为接口(FlyBehavior和QuackBehavior),不同的Fly()和Quack()行为实现这两个接口。这样的好处就是fly()和Quack()与Duck无关了,我们可以新增一些行为,既不会影响到现有行为类,也不会影响使用这些行为的Duck子类。

  • FlyBehavior各种各样的子类

    //拥有翅膀会飞翔
    public class FlyWithWings implements FlyBehavior {
        @Override
        public void fly() {
            System.out.println("使用翅膀飞翔了");
        }
    }
    
    //不会飞翔的飞翔子类
    public class FlyNoWay implements FlyBehavior {
        @Override
        public void fly() {
            System.out.println("我不会飞翔");
        }
    }
    
  • QuackBehavior的各种子类

    //呱呱叫
    public class Quack implements QuackBehavior{
        @Override
        public void quack() {
            System.out.println("呱呱叫");
        }
    }
    
    //吱吱叫
    public class Squeak implements QuackBehavior{
        @Override
        public void quack() {
            System.out.println("吱吱叫");
        }
    }
    
    //不会叫
    public class MuteQuack implements QuackBehavior {
        @Override
        public void quack() {
           System.out.println("不会叫");
        }
    }
    

整合鸭子的行为

Duck会将飞翔和叫喊的动作委托别人处理,而不是使用定义在Duck类/子类中的飞翔和叫喊方法。

  1. 在Duck类中加入“两个实例变量”,flyBeahvior和QuackBehavior,声明为接口类型而不是具体的实现类,每个Duck实例都会动态的设置这些变量以运行时引用正确的行为类型。

    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    
  2. 实现performFly和performQuack方法

    public void performQuack() {
        flyBehavior.fly();
    }
    
    public void performFly() {
        quackBehavior.quack();
    }
    

更多的整合

如何设置FlyBehavior和QuackBehavior的实例变量?我们不在乎flyBehavior和quackBehavior引用的对象究竟是谁,我们只关心该对象知道自己正确的行为就可以了。

public class MallardDuck extends Duck {
    @Override
    public void display() {
        System.out.println("绿头鸭");
    }

    public MallardDuck() {
        //初始化时指定MallardDuck正确的行为
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }
}

动态设定行为

在Duck子类的构造方法中指定行为固然可行,可是一旦指定就不能更改了。怎么办?在Duck超类中增加set方法,动态指定fly和quack行为。

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

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

//测试类
ModelDuck modelDuck = new ModelDuck();
modelDuck.setFlyBehavior(new FlyRocketPowered());
modelDuck.setQuackBehavior(new MuteQuack());
modelDuck.performFly();
modelDuck.performQuack();

针对接口编程

针对接口编程的真实意思是针对“超类型编程”,针对超类型编程这句话可以更明确的说成“变量的声明类型应该是超类型”,通常是一个抽象类或者是一个接口。比如Duck类中的FlyBehavior和QuackBehavior类型的变量。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值