策略设计模式解读

简介: 策略设计模式解读

问题引进

鸭子问题

编写鸭子项目,具体要求如下:
1) 有各种鸭子(比如 野鸭、北京鸭、水鸭等, 鸭子有各种行为,比如 叫、飞行等)
2) 显示鸭子的信息

传统方案解决鸭子问题的分析和代码实现

传统的设计方案(类图)

代码实现

Duck

1. public abstract class Duck {
2. public Duck() {
3.     }
4. public abstract void display();//显示鸭子信息
5. public void quack() {
6.         System.out.println("鸭子嘎嘎叫~~");
7.     }
8. public void swim() {
9.         System.out.println("鸭子会游泳~~");
10.     }
11. public void fly() {
12.         System.out.println("鸭子会飞翔~~~");
13.     }
14. }

PekingDuck  

1. public class PekingDuck extends  Duck{
2. @Override
3. public void display() {
4.         System.out.println("~~北京鸭~~~");
5.     }
6. 
7. //因为北京鸭不能飞翔,因此需要重写 fly
8. @Override
9. public void fly() {
10.         System.out.println("北京鸭不能飞翔");
11.     }
12. }

ToyDuck  

1. public class ToyDuck extends  Duck{
2. @Override
3. public void display() {
4.         System.out.println("玩具鸭");
5.     }
6. //需要重写父类的所有方法
7. public void quack() {
8.         System.out.println("玩具鸭不能叫~~");
9.     }
10. public void swim() {
11.         System.out.println("玩具鸭不会游泳~~");
12.     }
13. public void fly() {
14.         System.out.println("玩具鸭不会飞翔~~~");
15.     }
16. 
17. }

WildDuck  

1. public class WildDuck extends  Duck{
2. @Override
3. public void display() {
4.         System.out.println(" 这是野鸭 ");
5.     }
6. }

传统的方式实现的问题分析和解决方案

1) 其它鸭子,都继承了 Duck 类,所以 fly 让所有子类都会飞了,这是不正确的
2) 上面说的 1 的问题,其实是继承带来的问题:对类的局部改动,尤其超类的局部改动,会影响其他部分。会有溢出效应
3) 为了改进 1 问题,我们可以通过覆盖 fly 方法来解决 => 覆盖解决
4) 问题又来了,如果我们有一个玩具鸭子 ToyDuck, 这样就需要 ToyDuck 去覆盖 Duck 的所有实现的方法 => 解决思路 -》 策略模式 (strategy pattern)

策略模式基本介绍

基本介绍

1) 策略模式(Strategy Pattern)中,定义算法族(策略组),分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
2) 这算法体现了几个设计原则,第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而不是具体类(定义了策略接口);第三、多用组合/聚合,少用继承(客户通过组合方式使用策略)。

策略模式的原理类图

说明:从上图可以看到,客户 context 有成员变量 strategy 或者其他的策略接口,至于需要使用到哪个策略,我们可以在构造器中指定

策略模式解决鸭子问题

1) 应用实例要求

编写程序完成前面的鸭子项目,要求使用策略模式

2) 思路分析(类图)

策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为的变化独立于算法的使用者

代码实现

FlyBehavior  

1. public interface FlyBehavior {
2. 
3. void fly(); // 子类具体实现
4. }

BadFlyBehavior  

1. public class BadFlyBehavior implements  FlyBehavior{
2. 
3. @Override
4. public void fly() {
5.         System.out.println("飞翔技术一般");
6.     }
7. }

GoodFlyBehavior  

1. public class GoodFlyBehavior implements  FlyBehavior {
2. 
3. @Override
4. public void fly() {
5. // TODO Auto-generated method stub
6.         System.out.println(" 飞翔技术高超 ~~~");
7.     }
8. }

NoFlyBehavior  

1. public class NoFlyBehavior implements  FlyBehavior{
2. @Override
3. public void fly() {
4.         System.out.println("不会游泳");
5.     }
6. }

Duck  

1. public abstract class Duck {
2. //属性, 策略接口
3.     FlyBehavior flyBehavior;
4. public Duck() {
5.     }
6. public abstract void display();//显示鸭子信息
7. public void fly() {
8. //改进
9. if(flyBehavior != null) {
10.             flyBehavior.fly();
11.         }
12.     }
13. public void setFlyBehavior(FlyBehavior flyBehavior) {
14. this.flyBehavior = flyBehavior;
15.     }
16. }

ToyDuck  

1. public class ToyDuck extends  Duck{
2. public ToyDuck() {
3.         flyBehavior = new NoFlyBehavior();
4.     }
5. @Override
6. public void display() {
7.         System.out.println("玩具鸭");
8.     }
9. 
10. }

WildDuck  

1. public class WildDuck extends Duck{
2. @Override
3. public void display() {
4.         System.out.println("野鸭");
5.     }
6. 
7. public WildDuck() {
8.         flyBehavior =new GoodFlyBehavior();
9.     }
10. 
11. }

PekingDuck  

1. public class PekingDuck  extends  Duck{
2. 
3. //假如背景鸭可以游泳但飞翔技术一般
4. public PekingDuck() {
5.         flyBehavior =new BadFlyBehavior();
6.     }
7. 
8. @Override
9. public void display() {
10.         System.out.println("北京鸭");
11.     }
12. }

策略模式的注意事项和细节

1) 策略模式的关键是:分析项目中变化部分与不变部分
2) 策略模式的核心思想是:多用组合/聚合 少用继承;用行为类组合,而不是行为的继承。更有弹性
3) 体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用多重转移语句(if..else if..else)
4) 提供了可以替换继承关系的办法: 策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改变它,使它易于切换、易于理解、易于扩展
5) 需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞

相关文章
|
6月前
|
设计模式 安全 测试技术
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
137 0
|
6月前
|
设计模式 编解码 C++
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用(一)
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用
197 0
|
6月前
|
设计模式 存储 缓存
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用(二)
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用
109 0
|
1月前
|
设计模式 监控 算法
Java设计模式梳理:行为型模式(策略,观察者等)
本文详细介绍了Java设计模式中的行为型模式,包括策略模式、观察者模式、责任链模式、模板方法模式和状态模式。通过具体示例代码,深入浅出地讲解了每种模式的应用场景与实现方式。例如,策略模式通过定义一系列算法让客户端在运行时选择所需算法;观察者模式则让多个观察者对象同时监听某一个主题对象,实现松耦合的消息传递机制。此外,还探讨了这些模式与实际开发中的联系,帮助读者更好地理解和应用设计模式,提升代码质量。
Java设计模式梳理:行为型模式(策略,观察者等)
|
6月前
|
设计模式 监控 Java
设计模式 - 观察者模式(Observer):Java中的战术与策略
【4月更文挑战第7天】观察者模式是构建可维护、可扩展系统的关键,它在Java中通过`Observable`和`Observer`实现对象间一对多的依赖关系,常用于事件处理、数据绑定和同步。该模式支持事件驱动架构、数据同步和实时系统,但需注意避免循环依赖、控制通知粒度,并关注性能和内存泄漏问题。通过明确角色、使用抽象和管理观察者注册,可最大化其效果。
122 2
|
3月前
|
设计模式 JavaScript 前端开发
从工厂到单例再到策略:Vue.js高效应用JavaScript设计模式
【8月更文挑战第30天】在现代Web开发中,结合使用JavaScript设计模式与框架如Vue.js能显著提升代码质量和项目的可维护性。本文探讨了常见JavaScript设计模式及其在Vue.js中的应用。通过具体示例介绍了工厂模式、单例模式和策略模式的应用场景及其实现方法。例如,工厂模式通过`NavFactory`根据用户角色动态创建不同的导航栏组件;单例模式则通过全局事件总线`eventBus`实现跨组件通信;策略模式用于处理不同的表单验证规则。这些设计模式的应用不仅提高了代码的复用性和灵活性,还增强了Vue应用的整体质量。
50 1
|
4月前
|
设计模式 安全 Java
Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
102 0
|
6月前
|
设计模式 Java
设计模式之策略 Strategy
设计模式之策略 Strategy
42 1
|
设计模式 算法 搜索推荐
设计模式—策略(Strategy)模式
设计模式—策略(Strategy)模式
152 1
|
6月前
|
设计模式 缓存 安全
分析设计模式对Java应用性能的影响,并提供优化策略
【4月更文挑战第7天】本文分析了7种常见设计模式对Java应用性能的影响及优化策略:单例模式可采用双重检查锁定、枚举实现或对象池优化;工厂方法和抽象工厂模式可通过对象池和缓存减少对象创建开销;建造者模式应减少构建步骤,简化复杂对象;原型模式优化克隆方法或使用序列化提高复制效率;适配器模式尽量减少使用,或合并多个适配器;观察者模式限制观察者数量并使用异步通知。设计模式需根据应用场景谨慎选用,兼顾代码质量和性能。
54 0