大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~

希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!!

加油吧!未来可期!!

本文将介绍java设计模式之策略模式

案例引入

鸭子问题:编写鸭子项目,具体要求如下:

1) 有各种鸭子(比如 野鸭、北京鸭、水鸭等, 鸭子有各种行为,比如 叫、飞行等)

2) 显示鸭子的信息

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

1) 传统的设计方案(类图)

2) 代码实现

package strategy;/* <---这是包名
-*- coding:utf-8 -*-
作者:bob-coding
日期:2022年10月26日11:28
敲码百遍,其意多见!!冲冲冲!!!*/public class Strategy01 {public static void main(String[] args) {Duck wildDuck = new WildDuck();wildDuck.display();wildDuck.quack();wildDuck.fly();wildDuck.swim();System.out.println("==================");Duck pekingDuck = new PekingDuck();pekingDuck.display();pekingDuck.swim();pekingDuck.fly();pekingDuck.quack();System.out.println("===================");Duck toyDuck = new ToyDuck();toyDuck.display();toyDuck.swim();toyDuck.quack();toyDuck.fly();}
}class WildDuck extends Duck {@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println(" ~~野鸭子~~");}}class PekingDuck extends Duck {@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("~~北京鸭~~~");}//因为北京鸭不能飞翔,因此需要重写fly@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println("北京鸭不能飞翔");}}class ToyDuck extends Duck{@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("玩具鸭");}//需要重写父类的所有方法@Overridepublic void quack() {System.out.println("玩具鸭不能叫~~");}@Overridepublic void swim() {System.out.println("玩具鸭不会游泳~~");}@Overridepublic void fly() {System.out.println("玩具鸭不会飞翔~~~");}
}abstract class Duck {public Duck() {}public abstract void display();//显示鸭子信息public void quack() {System.out.println("鸭子嘎嘎叫~~");}public void swim() {System.out.println("鸭子会游泳~~");}public void fly() {System.out.println("鸭子会飞翔~~~");}}

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

1) 其它鸭子,都继承了Duck类,所以fly让所有子类都会飞了,这是不正确的

2) 上面说的1 的问题,其实是继承带来的问题:对类的局部改动,尤其超类的局部改 动,会影响其他部分。会有溢出效应

3) 为了改进1问题,我们可以通过覆盖fly 方法来解决 => 覆盖解决

4) 问题又来了,如果我们有一个玩具鸭子ToyDuck, 这样就需要ToyDuck去覆盖Duck 的所有实现的方法 => 解决思路 策略模式 (strategy pattern)

策略模式基本介绍

1) 策略模式(Strategy Pattern)中,定义算法族,分别封装起来,让他们之间可以 互相替换,此模式让算法的变化独立于使用算法的客户

2) 这算法体现了几个设计原则,第一、把变化的代码从不变的代码中分离出来; 第二、针对接口编程而不是具体类(定义了策略接口);第三、多用组合/聚合, 少用继承(客户通过组合方式使用策略)。

策略模式的原理类图

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

策略模式解决鸭子问题

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

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

3) 代码实现

package strategy02;/* <---这是包名
-*- coding:utf-8 -*-
作者:bob-coding
日期:2022年10月26日14:45
敲码百遍,其意多见!!冲冲冲!!!*/public class Strategy02 {public static void main(String[] args) {// TODO Auto-generated method stubWildDuck wildDuck = new WildDuck();wildDuck.fly();//ToyDuck toyDuck = new ToyDuck();toyDuck.fly();PekingDuck pekingDuck = new PekingDuck();pekingDuck.fly();//动态改变某个对象的行为, 北京鸭 不能飞pekingDuck.setFlyBehavior(new NoFlyBehavior());System.out.println("北京鸭的实际飞翔能力");pekingDuck.fly();}
}class WildDuck extends Duck {//构造器,传入FlyBehavor 的对象public  WildDuck() {// TODO Auto-generated constructor stubflyBehavior = new GoodFlyBehavior();}@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println(" 这是野鸭 ");}}class ToyDuck extends Duck{public ToyDuck() {// TODO Auto-generated constructor stubflyBehavior = new NoFlyBehavior();}@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("玩具鸭");}//需要重写父类的所有方法@Overridepublic void quack() {System.out.println("玩具鸭不能叫~~");}@Overridepublic void swim() {System.out.println("玩具鸭不会游泳~~");}}class PekingDuck extends Duck {//假如北京鸭可以飞翔,但是飞翔技术一般public PekingDuck() {// TODO Auto-generated constructor stubflyBehavior = new BadFlyBehavior();}@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("~~北京鸭~~~");}
}class GoodFlyBehavior implements FlyBehavior {@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println(" 飞翔技术高超 ~~~");}}class NoFlyBehavior implements FlyBehavior{@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println(" 不会飞翔  ");}}class BadFlyBehavior implements FlyBehavior {@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println(" 飞翔技术一般 ");}}abstract class Duck {//属性, 策略接口FlyBehavior flyBehavior;//其它属性<->策略接口QuackBehavior quackBehavior;public Duck() {}public abstract void display();//显示鸭子信息public void quack() {System.out.println("鸭子嘎嘎叫~~");}public void swim() {System.out.println("鸭子会游泳~~");}public void fly() {//改进if(flyBehavior != null) {flyBehavior.fly();}}public void setFlyBehavior(FlyBehavior flyBehavior) {this.flyBehavior = flyBehavior;}public void setQuackBehavior(QuackBehavior quackBehavior) {this.quackBehavior = quackBehavior;}
}interface QuackBehavior {void quack();//子类实现
}interface FlyBehavior {void fly(); // 子类具体实现
}

策略模式在JDK-Arrays 应用的源码分析

1) JDK的 Arrays 的Comparator就使用了策略模式

2) 代码分析+Debug源码+模式角色分析

public class Strategy {public static void main(String[] args) {// TODO Auto-generated method stub//数组Integer[] data = { 9, 1, 2, 8, 4, 3 };// 实现降序排序,返回-1放左边,1放右边,0保持不变// 说明// 1. 实现了 Comparator 接口(策略接口) , 匿名类 对象 new Comparator<Integer>(){..}// 2. 对象 new Comparator<Integer>(){..} 就是实现了 策略接口 的对象// 3. public int compare(Integer o1, Integer o2){} 指定具体的处理方式Comparator<Integer> comparator = new Comparator<Integer>() {public int compare(Integer o1, Integer o2) {if (o1 > o2) {return -1;} else {return 1;}};};// 说明/** public static <T> void sort(T[] a, Comparator<? super T> c) {if (c == null) {sort(a); //默认方法} else { if (LegacyMergeSort.userRequested)legacyMergeSort(a, c); //使用策略对象celse// 使用策略对象cTimSort.sort(a, 0, a.length, c, null, 0, 0);}}*///方式1 Arrays.sort(data, comparator);System.out.println(Arrays.toString(data)); // 降序排序//方式2- 同时lambda 表达式实现 策略模式Integer[] data2 = { 19, 11, 12, 18, 14, 13 };Arrays.sort(data2, (var1, var2) -> {if(var1.compareTo(var2) > 0) {return -1;} else {return 1;}});System.out.println("data2=" + Arrays.toString(data2));}}

说明:

  // 1. 实现了 Comparator 接口(策略接口) , 匿名类 对象 new Comparator<Integer>(){..}

        // 2. 对象 new Comparator<Integer>(){..} 就是实现了 策略接口 的对象

        // 3. public int compare(Integer o1, Integer o2){} 指定具体的处理方式

Comparator<Integer> comparator = new Comparator<Integer>() {

public int compare(Integer o1, Integer o2) {

if (o1 > o2) {

return -1;

} else {

return 1;

}

};

};

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

1) 策略模式的关键是:分析项目中变化部分与不变部分

2) 策略模式的核心思想是:多用组合/聚合少用继承;用行为类组合,而不是行为的继承更有弹性

3) 体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只 要添加一种策略(或者行为)即可,避免了使用多重转移语句(if..else if..else)

4) 提供了可以替换继承关系的办法: 策略模式将算法封装在独立的Strategy类中使得 你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展

5) 需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞大

Java设计模式之策略模式(UML类图分析+代码详解)相关推荐

  1. java设计模式之工厂模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  2. java设计模式之建造者模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  3. Java设计模式之模板方法模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  4. Java设计模式之组合模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  5. Java设计模式之中介者模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  6. Java设计模式之享元模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  7. Java设计模式之观察者模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  8. uml类图设计系统详解实例

    UML 类图 2009-11-21 14:03        by         闫妍,         1098         阅读,         ...         评论,       ...

  9. UML类图-六种关系详解

    UML基本介绍 UML--Unified modeling language UML(统一建模语言),是一种用于软件系统分析和设计的语言工具,它用于帮助软件开发人员进行思考和记录思路的结果 UML本身 ...

最新文章

  1. Android将联系人读取到LISTVIEW中遇到的问题!
  2. 一步一步SharePoint 2007之十四:实现Form认证(4)——创建管理帐户
  3. Burpsuite如何抓取使用了SSL或TLS传输的 IOS App流量
  4. Django使用Python操作数据库 --Django 1.8.2 文档(中文)部分笔记
  5. 解释型语言与编译型语言区别
  6. 随想录(推荐『步步惊芯 - 软核处理器内部设计分析』这本书)
  7. 从jsp向servlet传送数据的两种方式
  8. 如何转换html转化mp4,格式互转技巧:webm格式怎么转换mp4?
  9. dosbox使用教程
  10. 各国网站域名后缀名大全
  11. REST API 是什么?
  12. 网络摄像机目前的主流解决方案
  13. #梆梆安全杯#个人对APP安全的一些看法
  14. 删除xx天之前的文件夹python
  15. 解决开启TCP/IP筛选,使用Serv-u 需要开放的端口
  16. 电影类网站如何选择服务器
  17. 【HTML】HTML网页设计-----可爱多肉网页设计
  18. Scrapy之10行代码爬下电影天堂全站
  19. CF 183(div2)
  20. 书评:薛定谔猫与生物学鸽子:《生命是什么?》出版75周年记

热门文章

  1. python列表迭代器_Python 迭代器之列表解析
  2. 如何将传统 Node.js 项目部署到 Serverless
  3. 敏捷 冲刺_敏捷团队实现冲刺承诺的5种方式
  4. 在Microsoft Office Word 或者WPS中插入代码实现色彩高亮和保持原有格式
  5. QQ超级秘笈:免费申请QQ号码(转)
  6. 1.15 一键开关机电路
  7. python全栈开发工程师_【2018重磅巨献】老男孩Python高级全栈开发工程师第三期...
  8. window下Java诊断工具arthas 实操心得
  9. 驱动人生支持Intel显卡驱动30.0.100.9684且提供英特尔最新版显卡驱动
  10. 基于ESP32-CAM的RSTP协议网络摄像头