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
  • 以上内容均记载在我的开源项目中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
策略模式(Strategy Pattern)是Java设计模式中的一种行为型模式,它定义了一系列的算法,并将每个算法封装在独立的类中,使得它们可以互相替换。这样可以使得算法的变化独立于使用它们的客户端。 在策略模式中,有三个主要角色: 1. 环境类(Context):持有一个策略类的引用,用于调用具体的策略。 2. 抽象策略类(Strategy):定义了一个公共接口或抽象类,用于具体策略类的统一调用。 3. 具体策略类(Concrete Strategy):实现了抽象策略类定义的接口或抽象类,提供具体的算法实现。 使用策略模式可以实现算法的动态切换,增加新的算法也不会影响到已有的代码。例如,假设我们需要实现一个排序算法,可以定义一个抽象策略类 SortStrategy,然后具体的排序算法(如快速排序、归并排序等)分别实现 SortStrategy,并在环境类中持有 SortStrategy 的引用。这样,通过更换不同的 SortStrategy 对象,就可以在运行时选择不同的排序算法。 策略模式能够有效地解耦策略的定义和使用,提高代码的灵活性和可维护性。同时,它也符合面向对象设计原则中的"开闭原则"(对扩展开放,对修改关闭)和"单一职责原则"(一个类应该只有一个引起变化的原因)。 希望这个简要的介绍能够帮助到你对策略模式的理解。如果还有其他问题,可以继续提问!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值