Java设计模式之策略模式

策略模式

1. 基本介绍

  1. 策略模式,定义了算法族并分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
  2. 该模式体现了几个设计原则:
    1. 开闭原则:把变化的代码从不变的代码中分离出来;
    2. 依赖倒转原则:针对接口编程而不是具体的类;
    3. 合成复用原则:多使用组合/聚合,少使用继承。

2. 策略模式原理类图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QE0L4uil-1621652978331)(resource/1621648795166.png)]

3. 场景设定

编写鸭子项目:

  1. 有各自鸭子【野鸭、水鸭、小黄鸭、北京烤鸭】
  2. 各种鸭子的行为【飞、叫、飞行、游泳】
  3. 显示鸭子信息

4. 策略模式解决鸭子项目

4.1 思路分析

  1. 分别封装行为接口,实现算法族。超类里放置接口对象,在子类中设置具体的行为对象。
  2. 原则:分离变化部分,并封装成接口,基于接口编写具体细节,让行为的变化独立于算法的使用者。
  3. 类图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-213FUFpE-1621652978345)(resource/1621650083527.png)]

4.2 FlyBehavior接口及其实现

/**
 * @author: zipeng Li
 * 2021/5/22  10:14
 */
public interface FlyBehavior {
    void fly();
}

/**
 * @author: zipeng Li
 * 2021/5/22  10:14
 */
public class GoodFlyBehavior implements FlyBehavior{

    @Override
    public void fly() {
        System.out.println("我是飞行小能手。。。");
    }
}

/**
 * @author: zipeng Li
 * 2021/5/22  10:06
 */
public class NoFlyBehavior implements FlyBehavior{

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

4.3 QuackBehavior接口及其实现

/**
 * @author: zipeng Li
 * 2021/5/22  10:19
 */
public interface QuackBehavior {
    void quack();
}

/**
 * @author: zipeng Li
 * 2021/5/22  10:17
 */
public class GagaQuackBehavior implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("嘎嘎嘎嘎嘎嘎。。。。。");
    }
}

/**
 * @author: zipeng Li
 * 2021/5/22  10:17
 */
public class HahaQuackBehavior implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("hahahahhahaha...");
    }
}

4.4 Duck抽象及其实现

/**
 * @author: zipeng Li
 * 2021/5/22  10:18
 */
public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

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

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

    public void fly(){
        if(flyBehavior != null){
            flyBehavior.fly();
        }
    }

    public void quack(){
        if(quackBehavior != null){
            quackBehavior.quack();
        }
    }

    public abstract void display();
}

/**
 * @author: zipeng Li
 * 2021/5/22  10:26
 */
public class PekingDuck extends Duck {

    public PekingDuck() {
        quackBehavior = new HahaQuackBehavior();
        flyBehavior = new NoFlyBehavior();
    }

    @Override
    public void display() {
        System.out.println("我是北京烤鸭。。。");
    }
}

/**
 * @author: zipeng Li
 * 2021/5/22  10:29
 */
public class WildDuck extends Duck {

    public WildDuck() {
        flyBehavior = new GoodFlyBehavior();
        quackBehavior = new GagaQuackBehavior();
    }

    @Override
    public void display() {
        System.out.println("我是野鸭呀。。。");
    }
}

4.5 客户端测试

/**
 * @author: zipeng Li
 * 2021/5/22  10:31
 */
public class Client {
    public static void main(String[] args) {
        PekingDuck pekingDuck = new PekingDuck();
        pekingDuck.display();
        pekingDuck.quack();
        pekingDuck.fly();

        System.out.println("===================");
        WildDuck wildDuck = new WildDuck();
        wildDuck.display();
        wildDuck.fly();
        wildDuck.quack();

        // 动态改变
        wildDuck.setFlyBehavior(new NoFlyBehavior());
        wildDuck.fly();
    }
}
我是北京烤鸭。。。
hahahahhahaha...
我不会飞呀。。。
===================
我是野鸭呀。。。
我是飞行小能手。。。
嘎嘎嘎嘎嘎嘎。。。。。
我不会飞呀。。。

5. 策略模式在JDK-Arrays的应用

JDK 的 Arrays 的 Comparator 使用了策略模式

/**
 * @author: zipeng Li
 * 2021/5/22  10:46
 */
public class Strategy {
    public static void main(String[] args) {
        Integer[] data = {9, 1, 2, 8, 4, 3};
        /**
         * 1. Comparator 为策略接口,new Comparator<Integer>(){} 就是实现了策略接口的对象
         * 2. public int compare(Integer o1, Integer o2) {}方法则指定了具体的处理方法
         */
        Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                if (o1 > o2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        };
        Arrays.sort(data, comparator);
        System.out.println(Arrays.toString(data));
    }
}
// 根据传入的具体策略对象 c 进行相应排序
public static <T> void sort(T[] a, Comparator<? super T> c) {
  if (c == null) {
    sort(a);
  } else {
    if (LegacyMergeSort.userRequested)
      legacyMergeSort(a, c);
    else
      TimSort.sort(a, 0, a.length, c, null, 0, 0);
  }
}

6. 总结

  1. 优点:通过分析需求中的变与不变的部分,对变化的部分进行策略接口封装,其实现交由具体的子类。后期需要添加新的策略,则只需要添加新的类,而不用修改原有代码,体现了开闭原则。
  2. 缺点:每添加一种策略就需要新建一个类,会造成类过多的局面。

后序

  • 我是一名大三本科生,专业是软件工程【一本】。目前,正在准备找实习以及秋招,意向岗位是Java后端开发工程师。为此,在码云托管了一个项目,以整理我所有所学知识。涉及内容:计算机网络、操作系统、Java基础、主流Java后端框架、设计模式、Web前端框架等内容。欢迎大家访问我的开源项目编程之路
  • 码云地址:https://gitee.com/alizipeng/the-way-of-programming
  • 以上内容均记载在我的开源项目中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值