设计模式-01策略模式

news2024/12/27 10:04:39

1 什么是设计模式

先看一段设计模式总结之父们GOF在《设计模式 可复用面向对象软件的基础》一书中描述的一段话:
在这里插入图片描述
设计模式就是程序编码设计时的一些套路,这些套路都是经过前人千锤百炼总结出来的经验,由GoF总结出23种经典套路,即23种设计模式,天真的说我们只要深入理解了这23种套路,在编码过程中套用上去,就能得到结构良好的程序。当然设计模式并不规定死是这23种,毕竟本质是对编码经验的总结,如果你愿意你也可以发明一个设计模式,只是有没有别人认可罢了。

注:GoF是设计模式的经典名著Design Patterns: Elements of Reusable Object-Oriented Software(中译本名为《设计模式——可复用面向对象软件的基础》)的四位作者,他们分为是:Elich Gamma、Richard Helm、Ralph Johnson、以及John Vlissides。这四个人常被称为Gang of Four, 即四人组,简称GoF。

2 设计模式的六大原则

  • s - 单一职责
  • o - 开闭原则:扩展开放,修改关闭
  • l - 里氏替换原则:父类对象的引用换成子类对象时,调用的方法行为不能改变,即子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法
  • i - 接口隔离原则:将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性
  • d - 依赖倒转原则
  • d - 迪米特法制:只与你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)

事实上,设计模式就是对这六大原则的良好实践,只要我们在开发过程中严格遵循这六大原则,多思考,我们写出来的代码很大程度上会与设计模式中的某种模式不谋而合,这也是很多经验丰富,或源码看多的程序员就算没有接触过设计模式,但他们的代码就已经体现了设计模式的原因。

3 策略模式

3.1 意图

定义一系列算法,把它们一个个独立封装起来,并且使它们之间可以相互替换,该模式可以使得算法独立于它的使用者而变化。

3.2 适用性

  • 一个类中定义了多个行为,每个行为通过多个条件语句来控制。将这些行为分别定义为一个策略类。
  • 算法中的数据不能暴露给客户。使用策略模式可以避免暴露复杂的,与算法相关的数据结构。
  • 在某种情况下,需要使用到一个算法的不同变体。比如系统原来只有微信支付一种方式的,现在要增加支付宝支付的方式;
  • 许多相关的类仅仅只有行为有差异。“策略模式” 提供了一种从多个行为中选择一个行为来配置一个类的方法。

3.3 结构

Context
-Strategy strategy
«interface»
Strategy
+operate()
StrategyA
+operate()
StrategyB
+operate()
StrategyC
+operate()

3.4 参与角色

  • Stratety:策略簇的接口,所有具体的算法都实现该接口
  • ConcreteStrategy:具体的策略,如StrategyA
  • Context:上下文,维护一个对Strategy的引用;用一个ConcreteStrategy对象来配置。可以定义一个接口来让Strategy访问它的数据。

3.5 角色之间的协作

  • Strategy 和 Context相互作用以实现选定的算法。当算法被调用时,Context可以将该算法所需的所有数据都传递给该Strategy。或者,Context可以将自身作为一个参数传递给Strategy操作。这就让Strategy在需要时可以回调Context。
  • Context 将客户的请求转发给它的Strategy。客户通常创建并传递一个ConcreteStrategy给该Context,这样,客户仅与Context交互。通常有一系列的ConcreteStrategy类可供客户从中选择。

3.6 缺点

  • 用户必须了解不同的策略,就是一个用户要选择一个合适的策略就必须知道这些策略之间到有何不同。此时可能不得不向客户暴露具体的实现问题。因此仅当这些不同的行为和变体与客户相关时,才需要使用策略模式。
  • 增加了对象的数目

3.8 疑问

  • 为什么要有一个Context类呢,这是必须的吗?
    我认为这个Context不是必须的,或者说是模糊的,它也可以有用户来担任; 那么Context类的作用是什么呢?想象下在做项目过程中没有项目经理的角色,业务方(甲方)直接跟开发、测试进行交流,那是件多么糟糕的事情;当一个程序相当复杂的时候,Context是必要的,它可以存储一些必要的参数、数据结构,以简化用户对具体策略的调用,这也符合迪米特法则。

3.7 总结

总的来说就是依赖倒转 + 迪米特法则 + 依赖倒转 + 单一职责 的具体应用,用接口定义统一的入口,具体类来实现不同的行为,将接口组合到主类来进行调用;

3.8 示例

当前市面上有很多种支付方式,如支付宝(ALIPAY)、微信(WEIXINPAY)、银联(UNIPAY)、、苹果支付(APPLEPAY)等,以后可能还会出现各种pay,商家在收钱的时候要提供各种二维码,相当繁琐,现在我要做一个聚合支付的功能,就是提供一个二维码,不同客户端的消费者只需要扫一个二维码就可以完成支付。
这里我们假设用不同的App扫我这个码时都会给我们后端传一个标识用于识别是哪个app扫的码,比如支付宝就是ALIPAY、微信就是WEIXINPAY。

步骤一:先定义一个抽象的父类

public interface IPay {  
    void pay();  
}

步骤二:定义不同的实现类

@Service("ALIPAY")  
public class AliaPay implements IPay {  
     @Override  
     public void pay() {  
        System.out.println("===发起支付宝支付===");  
     }  
}  
@Service("WEIXINPAY")  
public class AliaPay implements IPay {  
     @Override  
     public void pay() {  
        System.out.println("===发起微信支付===");  
     }  
}  
@Service("UNIPAY")  
public class AliaPay implements IPay {  
     @Override  
     public void pay() {  
        System.out.println("===发起银联支付===");  
     }  
}  

步骤三:提供统一调用服务

@Service
public class PayService{  
	@Autowired
	Map<String,IPay> payStrategys;
   	/** 
   	* payWay 是支付方式,如 ALIPAY
   	*/
    public void pay(String payWay) {  
         payStrategys.get(payWay).pay();
     }  
}  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/757507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4028: 按位与

题目内容 输入格式 输入第一行一个整数 n n n。 第二行 n n n 个整数 a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a1​,a2​,⋯,an​。 输出格式 输出一行一个整数表示答案。 样例 1 输入 5 6 2 3 4 7 样例 1 输出 7 #include<bits/stdc.h> using namespace std…

怎样优雅地增删查改(三):业务用户的增删查改

文章目录 创建业务用户创建业务用户同步器创建业务用户应用服务增删改查 创建控制器测试按组织架构查询按职称查询 创建业务用户 区别于身份管理模块&#xff08;Identity模块&#xff09;的鉴权用户IdentityUser&#xff0c;业务用户&#xff08;BusinessUser&#xff09;是围…

【Python】正则表达式语法入门

目录 正则表达式 1、点&#xff1a;匹配所有字符 2、星号&#xff1a;重复匹配任意次 3、加号&#xff1a;重复匹配多次 4、花括号&#xff1a;匹配指定次数 5、贪婪模式和非贪婪模式 6、反斜杠&#xff1a;对元字符的转义 7、方括号&#xff1a;匹配几个字符之一 8、…

计算机科学与技术基础课程复习

文章目录 大学计算机基础 大学计算机基础 国防科技大学慕课 从算牌开始&#xff0c;记录数据 数据的计算规则 帕斯卡的加法器 计算自动化 图灵的梦想 乘10运算的图灵机 图灵记 根据状态和记录&#xff1b;根据控制器规则&#xff0c;从起始状态到结束状态&#xff0c;从…

less 笔记

1 margin-left 之后有 margin: 0 导致margin-left 无效 --> 不能重复定义 .btn-group {margin-left: calc(100% - 350px);display: inline-block;margin: 0; // 重复定义 导致上面 没有效果padding: 0; } 2 一定要F12检查元素 看各个div的宽度是否太长 导致靠左靠右 计算不…

5.1 Python高阶特性之递归函数

基本概念&#xff1a; 如果一个函数在内部调用自身本身&#xff0c;这个函数就是递归函数使用递归函数的优点是逻辑简单清晰&#xff0c;缺点是递归过深会导致栈溢出。【注意】 递归函数定义时&#xff0c; 一定存在某个条件能结束执行&#xff0c; 递归最重要的就是需要避免死…

免费使用Elasticsearch官网15天

注册登录 点击创建索引时候会给你展示一个密钥。这个密钥就是你的用户密码 如下图 你的服务地址大致样式如下 https://huihai.es.us-central1.gcp.cloud.es.io 这里需要你输入用户密码,上面图4&#xff08;图中&#xff09;&#xff0c;下载时候的用户密码 登录完成 这样就能…

【Python爬虫】CSDN热榜文章热门词汇分析

&#x1f4da; 前言 在信息时代&#xff0c;我们经常需要从大量的文章中获取有用的信息。本文将介绍如何使用Python进行数据处理&#xff0c;获取热榜文章的标题和标签&#xff0c;并使用jieba库进行数据分析。通过本文的学习&#xff0c;你将掌握获取和分析热榜文章数据的技巧…

[英语单词] components;

*[kәm’pәunәnt] n. 元件, 组件, 成分 a. 组成的, 构成的 【计】 组件 【化】 组分 【医】 成分; 组元(神经元组) 有很多地方使用这个单词&#xff0c;在组成整体时&#xff0c;作为单位一内的占有比率。那为什么不用portion&#xff1f; 这样每一个组成部分都是一个compon…

使用 YOLOv8 和 Streamlit 构建实时对象检测和跟踪应用程序:第 1 部分-介绍和设置

示例:图像上的对象检测 介绍 实时视频中的目标检测和跟踪是计算机视觉的一个重要领域,在监控、汽车和机器人等各个领域都有广泛的应用。 由于需要能够识别和跟踪对象、确定其位置并对它们进行实时分类的自动化系统,对视频帧中的实时对象检测和跟踪的需求日益增加。 在这…

疫情防控【并查集,离线查询,依次删除节点逆向转化为逐渐添上节点】

5 5 3 1 2 1 3 1 5 2 5 3 4 4 3 1 3 1 4 2 3 5 3 3 4 2 3 3 5 1 3 2 3 2 5 3 4输出样例: 1 2 3#include <bits/stdc.h> using namespace std; const int M1e35; const int N2e55; vector<int> e[N]; #define pii pair<int,int> vector<pii> query[M];…

day26 求一段连续子数组之和的最大值

题目描述 方法一&#xff1a;超出时间限制 思路&#xff1a;选一个起点&#xff0c;选一个终点&#xff0c;计算起点到终点的和&#xff1b;求max&#xff1b; 起点几种可能&#xff1a;0 到 size -1; 终点&#xff1a; 起点 到 size -1&#xff1b; int maxSubArray(int* nu…

【网站 全选和单选】js 实现-点击全选按钮时,所有的按钮都会被选中或取消选中。

要实现的效果如图&#xff1a; 代码实现&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport…

【基本绘图注释函数】——MatLab画图

目录索引 title&#xff1a;ylable&#xff1a;legend&#xff1a; title&#xff1a; 在绘图中添加标签。此类函数的输入是一个字符串。MATLAB 中的字符串是用双引号 (") 引起来的。 上面一部分画图代码这里省略 title("Sample Mass")ylable&#xff1a; 为y轴…

BUUCTF-EasyLogin

这是一道 Node.js 语言的题目&#xff0c;在此记录我在做这道题的思考过程。 这道题考的是 CVE-2022-23540. 简单测试 进入题目环境&#xff1a; 一个登录页面&#xff0c;由题目的名称 EasyLogin&#xff0c;我猜测这道题是身份认证缺陷的问题。不过&#xff0c;还是下意识测…

用主流编程语言解小学题

最近在网上刷到一个视频&#xff0c;内容是奶奶有60 元钱&#xff0c;去超市买了10元水果&#xff0c;收营员应该找奶奶多少钱?我一开始反应就是50元&#xff0c;后来想了想题干里没有说明这60元是怎么构成的&#xff0c;有可能是一张50元和一张10元&#xff0c;或者是3张20元…

day36-JSON+Servlet

0目录 JSONServlet 1.JSONServlet 1.1 创建工程/导入依赖/创建包/BaseDao...... 依赖&#xff1a;javax.servlet、jstl、mysql、taglibs、fastjson <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <…

sqli-labs 1-5 (手注和sqlmap)

sql注入 就是指web运用程序对用户输入数据的合法性没有判断&#xff0c;前端传入后端的参数是攻击者可控的&#xff0c;并且参数代入数据库查询&#xff0c;攻击者可以构造不同的SQL语句来实现对数据库的任意操作。 当然&#xff0c;SQL注入按照不同的分类方法可以分为很多种&a…

高等数学❤️第一章~第二节~极限❤️极限的概念与性质~函数极限(自变量趋于有限值时的极限)详解

【精讲】高等数学中函数极限&#xff1a;自变量趋于有限值时的极限 博主&#xff1a;命运之光的主页 专栏&#xff1a;高等数学 目录 【精讲】高等数学中函数极限&#xff1a;自变量趋于有限值时的极限 导言 二、函数极限自变量趋于有限值的判定方法 三、函数极限自变量趋于…

回溯算法详解(Back Tracking)

本文已收录于专栏 《算法合集》 目录 一、简单释义1、算法概念2、算法目的3、算法思想 二、核心思想三、图形展示四、算法实现1、实现思路2、代码实现TreeNode 类将数组处理成二叉树结构并且返回根节点进行搜索 五、算法分析1、时间复杂度2、空间复杂度3、算法稳定性 一、简单释…