当前位置: 首页 > news >正文

策略模式(Strategy Pattern)

编写鸭子项目,具体要求如下:
1) 有各种鸭子(比如 野鸭、北京鸭,水鸭等,鸭子有各种行为,比如 叫,飞行等)
2)显示鸭子的信息
传统方案解决鸭子问题
1) 传统的设计方法(类图)

 

2) 代码实现
创建一个 maven 项目 strategy
在项目路径下创建抽象父类 cn.baisee.strategy.Duck
public abstract class Duck {
/**
* 显示鸭子的信息
*/
public abstract void display();
/**
* 鸭子行为
*/
public void fly() {
System.out.println("鸭子会飞");
}
/**
* 鸭子行为
*/
public void quack() {
System.out.println("鸭子会叫");
}
}
创建野鸭子子类 cn.xs.strategy.WildDuck
public class WildDuck extends Duck {
/**
* 显示鸭子信息
*/
public void display() {
System.out.println(" 这是野鸭子 ");
}
}
创建北京鸭子类 cn.xs.strategy.PekingDuck
public class PekingDuck extends Duck {
/**
* 显示鸭子信息
*/
public void display() {
System.out.println(" 这是北京鸭 ");
}
/**
* 因为北京鸭不能飞翔,所以需要重写 fly
*/
@Override
public void fly() {
System.out.println("北京鸭不能飞翔");
}
}
创建玩具鸭子类 cn.xs.strategy.ToyDuck
public class ToyDuck extends Duck {
/**
* 显示鸭子信息
*/
public void display() {
System.out.println(" 这是玩具鸭 ");
}
/**
* 因为玩具鸭不能飞翔,所以需要重写 fly
*/
@Override
public void fly() {
System.out.println("玩具鸭不能飞翔");
}
/**
* 因为玩具鸭不能叫,所以需要重写 quack
*/
@Override
public void quack() {
System.out.println("玩具鸭不能叫");
}
}
分析传统方案:
1)其它鸭子,都继承了 Duck 类,所以 fly 让所有子类都会飞了,这是不正确的
2)上面说的 1 的问题,其实是继承带来的问题:对类的局部改动,尤其超类的局部改动,会影响其他
部分,会有溢出效应
3)为了改进 1 问题,我们可以通过覆盖 fly 方法来解决 => 覆盖解决
4)问题又来了,如果我们有一个玩具鸭子 ToyDuck ,这样就需要 ToyDuck 去覆盖 Duck 的所有实现的
方法 => 策略模式
基本介绍
1)策略模式(Strategy Pattern)中,定义算法族,分别封装起来,让他们之间可以互相替换,此模式
让算法的变化独立于使用算法的客户
2)这算法体现了几个设计原则,第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而
不是具体类(定义了策略接口);第三、所用组合/聚合,少用继承(客户通过组合方式使用策略)
策略模式解决鸭子问题:
分析:分别定义封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定飞行对象。原
则就是:分离变化部分,封装接口,基于接口编程各种功能,此模式让行为的变化独立于算法的使用者
针对飞行这个行为,我们定义策略接口 cn.xs.strategy.FlyBehavior
public interface FlyBehavior {
/**
* 抽象的飞行方法
*/
void fly();
}
定义三种飞行行为实现飞行策略接口
第一个,飞行能力很好的行为 cn.xs.strategy.GoodFlyBehavior
public class GoodFlyBehavior implements FlyBehavior {
/**
* 实现飞行方法
*/
public void fly() {
System.out.println("飞翔技术高超");
}
}
第二个,飞行能力不好的行为 cn.xs.strategy.BadFlyBehavior
public class BadFlyBehavior implements FlyBehavior {
/**
* 实现飞行方法
*/
public void fly() {
System.out.println("飞翔能力一般");
}
}
第三个,没有飞行能力 cn.xs.strategy.NoFlyBehavior
public class NoFlyBehavior implements FlyBehavior {
/**
* 实现飞行方法
*/
public void fly() {
System.out.println("没有飞行能力");
}
}
将策略接口聚合进 Duck
public abstract class Duck {
/* 聚合飞翔行为策略接口 */
protected FlyBehavior flyBehavior;
/**
* 显示鸭子的信息
*/
public abstract void display();
/**
* 鸭子行为
*/
public void fly() {
if (flyBehavior != null) {
flyBehavior.fly();
}
}
/**
* 鸭子行为
*/
public void quack() {
System.out.println("鸭子会叫");
}
}
Duck 子类中将 FlyBeHavior 初始化
野鸭子:
/**
* 初始化飞行行为
*/
public WildDuck() {
flyBehavior = new GoodFlyBehavior();
}
北京鸭:
/**
* 初始化飞行行为
*/
public PekingDuck() {
flyBehavior = new NoFlyBehavior();
}
玩具鸭:
/**
* 初始化飞行行为
*/
public ToyDuck() {
flyBehavior = new NoFlyBehavior();
}
去掉所有子类中重写的 fly 方法
新建cn.xs.strategy.Client 测试类进行测试:
public class Client {
/**
* 测试方法
*
* @param args
*/
public static void main(String[] args) {
System.out.println("======野鸭子======");
WildDuck wildDuck = new WildDuck();
wildDuck.fly();
System.out.println("======北京鸭======");
PekingDuck pekingDuck = new PekingDuck();
pekingDuck.fly();
System.out.println("======玩具鸭======");
ToyDuck toyDuck = new ToyDuck();
toyDuck.fly();
}
}
运行 main 方法:

 

 

策略模式在 jdk 中的使用:
1jdk Arrays Comparator 就使用了策略模式
2)代码演示:
Integer[] arr = {1,5,3,7,8};
Arrays.sort(arr, new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
函数式接口 Comparator 就是一个策略接口,compare 就是一个排序的行为,
我们可以自己定义不同的 实现,来对数组进行各种排序,不同的排序规则就是不同的行为,就跟鸭子的飞行能力一样
策略模式的注意事项和细节:
1)策略模式的关键是:分析项目中变化部分与不变部分
2)策略模式的核心思想:多用组合/聚合 少用继承;用行为类组合,而不是行为的继承。更具弹性
3)体现了 "对修改关闭,对扩展开放" 原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用多重转移语句(if...else if...else
4)提供了可以替换继承关系的方法:策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改变它,使它易于切换、易于理解、易于扩展
5)需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞大

相关文章:

策略模式(Strategy Pattern)

编写鸭子项目&#xff0c;具体要求如下&#xff1a; 1&#xff09; 有各种鸭子&#xff08;比如 野鸭、北京鸭&#xff0c;水鸭等&#xff0c;鸭子有各种行为&#xff0c;比如 叫&#xff0c;飞行等&#xff09; 2&#xff09;显示鸭子的信息 传统方案解决鸭子问题 1&#xff0…...

《Qt6开发及实例》6-2 Qt6基础图形的绘制

目录 一、绘图框架设计 二、绘图区的实现 2.1 PaintArea类 2.2 PaintArea类讲解 三、主窗口的实现 3.1 MainWidget类 3.2 MainWidget类讲解 3.3 槽函数编写 3.5 其他内容 一、绘图框架设计 界面 两个类 ​ 二、绘图区的实现 2.1 PaintArea类 ​paintarea.h #ifndef…...

LeetCode 382. 链表随机节点

原题链接 难度&#xff1a;middle\color{orange}{middle}middle 题目描述 给你一个单链表&#xff0c;随机选择链表的一个节点&#xff0c;并返回相应的节点值。每个节点 被选中的概率一样 。 实现 SolutionSolutionSolution 类&#xff1a; Solution(ListNodehead)Solution…...

iOS开发AppleDeveloper中给别人授权开发者权限后,对方一直显示不了我的开发账号team

在iOS开发经常出现多人协作开发的情况。这时我们通常要发邮件邀请别的用户为开发者或者app管理就可以开发我们自己的项目了。但是这次我给别人授权开发者权限后&#xff0c;发现别人权限中没有证书相关权限如图&#xff1a;并且别人登录该账号后&#xff0c;在xcode中只有一个看…...

FreeRTOS数据类型和编程规范

目录 数据类型 变量名 函数名 宏的名 数据类型 每个移植的版本都含有自己的portmacro.h头文件&#xff0c;里面定义了2个数据类型 TickType_t FreeRTOS配置了一个周期性的时钟中断&#xff1a;Tick Interrupt每发生一次中断&#xff0c;中断次数累加&#xff0c;这被称为t…...

【python知识】win10下如何用python将网页转成pdf文件

一、说明 本篇记录一个自己享用的简单工具。在大量阅读网上文章中&#xff0c;常常遇到一个专题对应多篇文章&#xff0c;用浏览器的收藏根本不够。能否见到一篇文章具有搜藏价值&#xff0c;就转到线下&#xff0c;以备日后慢慢消化吸收。这里终于找到一个办法&#xff0c;将在…...

C语言常见关键字

写在前面 这个博客是结合C语言深度解剖这本书和我以前学的知识综合而成的,我希望可以更见详细的谈一下C语言的关键字,内容有点多,有错误还请斧正. 常见关键字 下面我们说下C语言的关键字,所谓的关键字是指具有特定功能的单词,我们可以使用关键字来帮助我们完成不同的事物.C语…...

【MT7628】固件开发-SDK4320添加MT7612E WiFi驱动操作说明

解压5G WiFi MT7612E驱动1.1解压指令 tar -xvf MT76x2E_MT7620_LinuxAP_V3.0.4.0_P2_DPA_20160308.tar.bz2 1.2解压之后会出现以下两个目录 rlt_wifi rlt_wifi_ap 1.3将解压后的文件拷贝到系统下 拷贝路径 RT288x_SDK/source/linux-2.6.36.x/drivers/net/wireless 内核中打开驱…...

如何从手工测试进阶自动化测试?阿里10年测开经验分享...

随着行业的竞争加剧&#xff0c;互联网产品迭代速度越来越快&#xff0c;QA 与测试工程师都需要在越来越短的测试周期内充分保证质量。可是&#xff0c;App 测试面临着很多挑战&#xff0c;比如多端发布、多版本发布、多机型发布等等&#xff0c;导致了手工测试很难完全胜任。因…...

C++复习笔记11

1. vector是表示可变大小数组的序列容器。 2. 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而且它的大小会被…...

【MT7628】固件开发-SDK4320添加MT7628 WiFi驱动操作说明

解压2.4G WiFi MT7628驱动1.1解压指令 tar -xvf MT7628_LinuxAP_V4.1.0.0_DPA_20160310.tar.bz2 1.2解压之后会出现以下两个目录 mt_wifi mt_wifi_ap 1.3将解压后的文件拷贝到系统下 拷贝路径 RT288x_SDK/source/linux-2.6.36.x/drivers/net/wireless 内核中打开驱动编译修改R…...

C#开发的OpenRA游戏加载界面的实现

C#开发的OpenRA游戏加载界面的实现 游戏的UI是一个游戏必备, 但是游戏的UI都是自己处理的,不能使用像Windows自带的UI。 这样游戏的UI,其实也是使用游戏的方式来显示的, 只不过使用了低帧率的方式来显示。 比如OpenRA游戏界面,就会显示如下: 游戏的界面有很多,先从一个简…...

渲染农场优势是什么_云渲染农场怎么用?

在回答渲染农场的优势这个问题之前&#xff0c;我先申明一下本文中提到的渲染农场/云渲染平台/云渲染农场&#xff0c;都特指CG领域内的专业3D渲染平台&#xff0c;有一些文章会强调这个叫法的区别&#xff0c;但是业内一般都不会分这么细&#xff0c;所以也就不赘述了。渲染农…...

SoapUI、Jmeter、Postman三种接口测试工具的比较分析

目录 前言 1. 用例组织方式 2. 支持的接口类型与测试类型 3. 配置不同接口类型 4. 自定义变量以及变量的作用域 5. 数据源、生成器&#xff0c;进行参数化 6. 流程控制 7. 结果解析、展示 8. 断言 9. 脚本扩展能力 10. 团队协作 总结 重点&#xff1a;配…...

Python内置函数 — sort,sorted

1、sort 列表的属性方法&#xff0c;对列表进行排序&#xff0c;默认升序&#xff0c;返回None值。 源码注释&#xff1a; """ Sort the list in ascending order and return None.The sort is in-place (i.e. the list itself is modified) and stable (i.e.…...

mysql事务隔离级别

mysql锁机制及原理1.隔离级别2.实践2.1查看事务隔离级别2.2 设置隔离级别2.3 不可重复读2.4 幻读3.幻读怎么解决3.1 Record Lock3.2 Gap Lock3.3 Next-Key Lock引用&#xff1a;https://blog.csdn.net/xinyuan_java/article/details/1284932051.隔离级别 SERIALIZABLE(序列化)…...

【C++】string类(下)

文章目录1.迭代器(正向遍历)begin有两个版本2.反向迭代器(反向遍历)rbegin由两个版本3. at4. insert ——头插在pos位置前插入一个字符串在pos位置前插入n个字符在迭代器前插入一个字符5. erase从pos位置开始删除len个字符从迭代器位置开始删除6. replace——替换从pos位置开始…...

Elasticsearch: Prefix queries - 前缀查询

Prefix queries 被用于在查询时返回在提供的字段中包含特定前缀的文档。有时我们可能想使用前缀查询单词&#xff0c;例如 Leonardo 的 Leo 或 Marlon Brando、Mark Hamill 或 Martin Balsam 的 Mar。 Elasticsearch 提供了一个前缀查询&#xff0c;用于获取匹配单词开头部分&a…...

GEE学习笔记 七十七:GEE学习方法简介

这是一篇关于学习方法的思考探索&#xff0c;当然我不会大篇文章介绍什么学习方法&#xff08;因为我也不是这方面的专家?&#xff09;&#xff0c;这个只是总结一下我是如何学习GEE以及在学习中遇到问题时如何解决问题的。我写这篇文章的目的就是在和一些学习GEE的新同学接触…...

20基于主从博弈的智能小区代理商定价策略及电动汽车充电管理MATLAB程序

参考文档&#xff1a;《基于主从博弈的智能小区代理商定价策略及电动汽车充电管理》基本复现仿真平台&#xff1a;MATLABCPLEX/gurobi平台优势&#xff1a;代码具有一定的深度和创新性&#xff0c;注释清晰&#xff0c;非烂大街的代码&#xff0c;非常精品&#xff01;主要内容…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...