设计模式-策略模式

参考:head-first-设计模式

定义

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

光看定义有点懵逼,接下使用代码一步步改进,慢慢形成策略模式
看完相信你会对策略模式有所了解

项目结构

在这里插入图片描述

类图

在这里插入图片描述

问题描述

一般鸭子的行为分为游泳,外形,飞,叫
游泳和外形是每个鸭子都有的,而飞和叫不是都有

我们一般实现都是直接写Duck抽象类,然后申明这4个方法

public abstract class Duck {
    public abstract void flly();
    
    public abstract void quack();
    
    public abstract void swim();

    public abstract void display();
}

然后具体鸭子类继承Duck类,实现这4个方法
但是有些鸭子不会飞,比如橡皮鸭,有些不会叫,比如木头鸭
这样每个鸭子都实现了飞和叫的方法,就会产生很多无用的代码

改进一下

申明两个接口flyable和quackable,分别申明fly和quack方法
会飞的鸭子才实现flyable的接口
会叫的鸭子才实现quackable接口
这样就解决了不能飞的鸭子还要实现fly()方法的问题
但是这样也有问题
所有会飞的鸭子都要实现fly()方法,当两个鸭子fly的方式相同时,两个fly的实现差不多,这样就会产生很多重复的代码,实现类不能够复用

再改进一下

申明两个接口FlyBehavior和QuackBehavior,分别申明fly和quack方法

public interface FlyBehavior {
    void fly();
}
public interface QuackBehavior {
    void quack();
}

根据行为的不同,分别实现这两个接口
飞两种形态

public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("FlyNoWay");
    }
}
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("FlyWithWings");
    }
}

叫三种形态

public class MuteQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("MuteQuack");
    }
}
public class Quack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Quack");
    }
}
public class Squack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Squack");
    }
}

然后在Duck类中申明这两个接口,接口编写执行行为的方法,performFly和performQuack

public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

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

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

    public abstract void swim();

    public abstract void display();
}

测试一下,看看如何使用
首先编写一个鸭子的具体实现类,在构造方法中指明使用的是哪个形态的飞和叫

public class MallardDuck extends Duck {
    @Override
    public void swim() {
        System.out.println("swim");
    }

    @Override
    public void display() {
        System.out.println("green");
    }

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

接着写测试代码

@RunWith(SpringRunner.class)
@SpringBootTest
public class celueDemoApplicationTests {

    @Test
    public void contextLoads() {
        Duck duck = new MallardDuck();
        duck.performFly();
        duck.performQuack();
    }
}

结果展示,控制台打印
在这里插入图片描述
这种方式必须在实现具体鸭子的时候在构造方法中指明是哪种方式,所以还是有点问题

再改进一下

在Duck类中新增方法setQuack和setFly,如下所示

public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

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

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

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

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

    public abstract void swim();

    public abstract void display();
}

这样就能在代码运行中随时修改飞和叫的形式
测试使用一下

@RunWith(SpringRunner.class)
@SpringBootTest
public class celueDemoApplicationTests {

    @Test
    public void contextLoads() {
        Duck duck = new MallardDuck();
        duck.performFly();
        duck.performQuack();
        //修改飞的形式为不能飞
        duck.setFly(new FlyNoWay());
        //修改呱呱叫为吱吱叫
        duck.setQuack(new Squack());
        duck.performFly();
        duck.performQuack();
    }
}

结果展示
在这里插入图片描述
这就是策略模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值