模版与策略模式
一,怎么选择
如果需要固定的执行流程,选模版
如果不需要固定的执行流程,只需要对一个方法做具体抽象,选策略
参考文章:
常用设计模式汇总,告诉你如何学习设计模式
二,常用写法
子类 extends absClass implements businiessInterface
absClass = absClass impements strategyInterface
样例与详细分析
public class ECCBMS195ServiceImpl extends AbstractBmsService implements ECCBMS195Service {
public abstract class AbstractBmsService implements BmsService {
一,策略接口
方法1:抽象类实现
方法2:子类实现,标识策略对象。后续工厂模式有用
public interface strategyInterface {boolean execute(EccMessageReqVO eccMessageReqVO) throws Exception;BmsServiceEnum getType();
}
二,抽象类
absClass
@Override
@Transactional
public boolean execute(EccMessageReqVO eccMessageReqVO) throws Exception {this.process(eccMessageReqVO);return true;
}public abstract void process(EccMessageReqVO eccMessageReqVO) throws Exception;
三,业务接口 businiessInterface
public interface EccBms111Service {void bms111Execute(ReqEccBms111VO reqEccBms110VO) throws Exception;}
四,子类
1,实现业务接口逻辑businiessInterface
public void bms111Execute(ReqEccBms111VO reqEccBms111VO) throws Exception {}
2,实现抽象方法 process。且抽象接口中,调用具体业务接口
public void process(EccMessageReqVO eccMessageReqVO) throws Exception {this.bms111Execute(reqEccBms111VO);}
3,实现枚举接口,标识自身策略对象类型
@Override
public BmsServiceEnum getType() {return BmsServiceEnum.ECC_BMS111;
}
5,工厂模式
初始化对象,提供获取具体对象接口
@Component
public class BmsServiceSelector implements InitializingBean {private static final Map<BmsServiceEnum, BmsService> serviceMap = new HashMap<>();@Resourceprivate List<BmsService> EccServices;@Overridepublic void afterPropertiesSet() throws Exception {for (BmsService service : EccServices) {serviceMap.put(service.getType(), service);}}public BmsService getService(BmsServiceEnum bmsServiceEnum) {if (null == bmsServiceEnum){throw new IllegalArgumentException("操作失败!");}return serviceMap.get(bmsServiceEnum);}
}
6,调用方
1,首先调用者,不同业务场景有自己的唯一标识,比如MQ下发时,不同的场景,MQ tag不同
根据tag - > 获取枚举 -》根据枚举 -〉 获取具体对象 - 》 用具体对象调用具体逻辑
2,调用执行逻辑是策略接口中方法,execute,这个接口有抽象类实现(非子类实现)
public interface BmsService {boolean execute(EccMessageReqVO eccMessageReqVO) throws Exception;BmsServiceEnum getType();}
BmsServiceEnum bmsServiceEnum = BmsServiceEnum.fromValue(vo.getTags());
BmsService bmsService = bmsServiceSelector.getService(bmsServiceEnum);
if(Objects.isNull(bmsService)) return true;
vo.setEccServiceName(bmsServiceEnum.getName());
bmsService.execute(vo);
疑问:如果不在BmsService中定义,删除,直接在抽象类中写个,普通的方法execute(即模版方法),有问题吗?
你看下有问题吗,报错了。调用者获取的是策略接口对象BmsService,是这个接口调用的。
再次体现,针对接口编程,非实现类编程。
为什么有此一问呢?是不是想到了文章中这里,策略模式中定义Context,里面定义了抽象类,
private penguin _penguin;
然后直接根据抽象类对象,调用抽象类中抽象接口与普通接口。
违背了设计原则:依赖接口,非依赖具体类。
public class behaviorContext {private penguin _penguin;public behaviorContext(penguin newPenguin) {_penguin = newPenguin;}public void setPenguin(penguin newPenguin) {_penguin = newPenguin;}public void everyDay() {_penguin.eating();_penguin.sleeping();_penguin.beating();}
}
实际使用中,会这样用吗,依赖抽象类。见过如下
场景:不同业务场景,导入excel,读取excel数据,并返回不同场景的对象(用通配符T)
public class BatchVehicleInfoController {private final ExcelUploadDataService<VehicleCoreExcel> vehicleCoreDataExcelService;
}
public abstract class ExcelUploadDataService<T> {/*** excel 读取含表头** @param excelInputStream* @return*/public ExcelReadResult<T> readWithHead(final InputStream excelInputStream, final Class<T> clazz) {}}
三,这一波下来用了什么设计模式
哪一波?上文【常用写法】
子类 extends absClass implements businiessInterface
absClass = absClass impements strategyInterface
模版
抽象类中定义了模版方法execute(只有一个行为process),模版方法中,调用了抽象接口 process。
抽象类 + 模版方法 + 抽象接口(子类实现),根据这三点可以理解为模版模式
public boolean execute(EccMessageReqVO eccMessageReqVO) throws Exception { this.process(eccMessageReqVO); return true; }
策略
抽象类 + 抽象接口,可以理解为策略模式。这也是策略的一般格式。
二者异同
好像与模版模式,一样,那最大的不同是什么
我认为是调用者,获取对象的方式不同
模版模式,每一个场景对象直接new的。参考这篇文档
常用设计模式汇总,告诉你如何学习设计模式
如下
public class test {public static void main(String[] args) {System.out.println("littlePenguin:");littlePenguin penguin1 = new littlePenguin();penguin1.everyDay();System.out.println("middlePenguin:");middlePenguin penguin2 = new middlePenguin();penguin2.everyDay();System.out.println("bigPenguin:");bigPenguin penguin3 = new bigPenguin();penguin3.everyDay();}
}
模版模式,优化了调用者对象的创建方式
文章描述如下
这里就是策略模式的重点,我们再看一下策略模式的定义“我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的context对象”,那么该contex对象如下:
public class behaviorContext {private penguin _penguin;public behaviorContext(penguin newPenguin) {_penguin = newPenguin;}public void setPenguin(penguin newPenguin) {_penguin = newPenguin;}public void everyDay() {_penguin.eating();_penguin.sleeping();_penguin.beating();}
}
最后看调用方式:
public class test {public static void main(String[] args) {behaviorContext behavior = new behaviorContext(new littlePenguin());behavior.everyDay();behavior.setPenguin(new middlePenguin());behavior.everyDay();behavior.setPenguin(new bigPenguin());behavior.everyDay();}
}
有何感想: 上面强调了两个对象
策略的对象 + context对象
你看最后调用的时候,还是new了,对应和模版模式相同。
只是包了一层,方法的真正的调用者不同
模版:new的具体对象直接调用
littlePenguin penguin1 = new littlePenguin();
penguin1.everyDay();
策略:抽象对象调用
把调用者对象包了一下,且这个对象是一个抽象的
private penguin _penguin;
调用者还是对象,是不过这个对象不是new的具体对象,是一个抽象对象
这也体现了设计原则:针对接口编程,不要针对实现编程
public void everyDay() {_penguin.eating();_penguin.sleeping();_penguin.beating();}
那context对象的作用是什么?
再看下概念:一个行为随着策略对象改变而改变的context对象
总体来看,还是创建对象,并封装了一个调用具体逻辑的方法
public void everyDay() {_penguin.eating();_penguin.sleeping();_penguin.beating();}
但是我觉得封装方法不是重点,封装的方法,可以看作就一个抽象方法 _penguin.beating();
它的作用还是,提供了一个创建对象的入口。
一句话,它做的工厂模式的事
工厂
上面第三点,完全体现了,工厂模式
四,总结
现在回头看,模版与策略主要区别
1,模版有一套固定行为,策略无
2,策略封装了,对象的创建与获取。像是一个不那么完整的工厂模式(对比上面第5点)
相关文章:

模版与策略模式
一,怎么选择 如果需要固定的执行流程,选模版 如果不需要固定的执行流程,只需要对一个方法做具体抽象,选策略 参考文章: 常用设计模式汇总,告诉你如何学习设计模式 二,常用写法 子类 exten…...

SQL-Python
师从黑马程序员 数据库介绍 数据库就是存储数据的库 数据组织:库->表->数据 数据库和SQL的关系 MySQL的基础命令 SQL基础 SQL语言的分类 SQL的语法特征 DDL-库管理 show DATABASES;use sys;SELECT database();CREATE DATABASE test CHARSET utf-8;SHOW D…...

mysql索引以及优化
索引的作用 在数据库表中对字段建立索引可以大大提高查询速度 mysql索引类型 普通索引唯一索引: 唯一索引列的值必须唯一允许有空值,如果是组合索引,则列值的组合必须唯一create unique index indexName on mytable(username(length))修改表结…...

【pytorch06】 维度变换
常用API view/reshapesqueeze/unsqueezetranspose/t/permuteexpand/repeat view和reshape view操作的基本前提是保证numel()一致 a.view(4,28*28)的物理意义是把行宽以及通道合并在一起,对于4张图片,我们直接把所有数据都合在一起,用一个7…...

移动Web开发实战内容要点!!!
移动web开发 目录 移动web开发 第一章、Web开发标准与网页网站制作介绍 1.1Web开发标准 1.2网页基本构成元素 第二章、Web开发技术基础 2.1HTML的主要特点: 2.2HTML基本知识 2.3CSS样式 2.4JavaScript 第三章、打造移动Web应用程序 3.1为什么Android会成…...

spdlog生产者消费者模式
spdlog生产者消费者模式 spdlog提供了异步模式,显示的创建async_logger, 配合环形队列实现的消息队列和线程池实现了异步模式。异步logger提交日志信息和自身指针, 任务线程从消息队列中取出消息后执行对应的sink和flush动作。 1. 环形队列 1.1 环形队…...

日语 13 14
13. スピーチの依頼 いらい 自信 自信 自信 自信 自信 じしん 折り入って 折り入って 折り入って おりいって 诚恳 頼み 頼み 頼み 頼み 頼み たのみ 请求 整備 整備 整備 整備 整備 せいび 维修 肥満 肥満 肥満 肥満 肥満 ひまん 肥胖 権利 …...

初学者应该掌握的MySQL数据库的基本组成部分及概念
MySQL数据库作为一种开源的关系型数据库管理系统,被广泛应用于Web应用开发和数据存储。它具有高性能、易用性和可靠性等特点,是开发者们的首选之一。在本篇文章中,我们将详细介绍MySQL数据库的核心组成部分,帮助你深入理解这个强大…...

四川汇聚荣科技有限公司怎么样?
在探讨一家科技公司的综合实力时,我们往往从多个维度进行考量,包括但不限于公司的发展历程、产品与服务的质量、市场表现、技术创新能力以及企业文化。四川汇聚荣科技有限公司作为一家位于中国西部的科技企业,其表现和影响力自然也受到业界和…...

数据仓库和数据库有什么区别?
一、什么是数据仓库二、什么是数据库三、数据仓库和数据库有什么区别 一、什么是数据仓库 数据仓库(Data Warehouse)是一种专门用于存储和管理大量结构化数据的信息系统。它通过整合来自不同来源的数据,为企业提供统一、一致的数据视图&…...

计算子网掩码
例题 如果子网掩码是255.255.192.0, 那么下面主机()必须通过路由器才能与主机129.23.144.16通信( 1分 )A.129.23.148.127B. 129.23.191.21C. 129.23.127.222D. 129.23.130.33计算 要确定哪些主机必须通过路由器才能与…...

JVM 垃圾收集算法
首先我们要知晓,垃圾收集是建立在两个分代假说之上的: ①弱分代假说:绝大多数对象都是朝生夕灭的 ②强分代假说:熬过越多次垃圾收集的对象就越难消亡 收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄分配…...

安装虚拟环境
自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Flask依赖两个外部库:Werkzeug和Jinja2。Werkzeug是一个WSGI(在Web应用和多种服务器之间的标准 Python 接口)工具…...

【ai】tx2-nx:安装深度学习环境及4.6对应pytorch
参考:https://www.waveshare.net/wiki/Jetson_TX2_NX#AI.E5.85.A5.E9.97.A8 英伟达2021年发布的的tritionserver 2.17 版本中,backend 有tensorflow1 和 onnxruntime ,他们都是做什么用的,作为backend 对于 triton 推理server意义是什么,是否应该有pytorch? Triton Infer…...

华为某员工爆料:三年前985本科起薪30万,现在硕士起薪还是30w,感慨互联网行情变化
“曾经的30万年薪,是985本科学历的‘标配’,如今硕士也只值这个价?” 一位华为员工的爆料,揭开了互联网行业薪资变化的冰山一角,也引发了不少人的焦虑:互联网人才“通货膨胀”的时代,真的结束了…...

Java基础--AOP--1.概述
一、AOP简介 AOP(Aspect Oriented )即为面向切面编程,也可称为面向方法编程,是方法增强的一种途径,通常可用于记录操作日志、权限空值、事务管理等等;Spring框架中的事务底层就是AOP。 二、AOP的组成 1、连接点&…...

【计算机网络仿真实验-实验3.1、3.2】交换路由综合实验
实验3.1 交换路由综合实验——作业1 一、实验目的 运用实验二(可前往博主首页计算机网络专栏下查看)中学到的知识,将这个图中的PC机连接起来组网并分析,本篇涉及代码以截图展示,过于简单的代码及操作不再详细介绍&…...

RSA密码系统的特定密钥泄露攻击与Coppersmith方法的应用
PrimiHub一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全、密码学、联邦学习、同态加密等隐私计算领域的技术和内容。 RSA密码系统作为当前最广泛使用的公钥加密算法之一,其安全性依赖于大整数分解问题的困难性。然而,随着计…...

从零开始精通Onvif之音视频流传输
💡 如果想阅读最新的文章,或者有技术问题需要交流和沟通,可搜索并关注微信公众号“希望睿智”。 概述 Onvif协议的核心作用之一,是定义了如何通过网络访问和控制IP摄像机和其他视频设备。Onvif协议不仅涉及设备发现、设备管理&…...

CentOS 7、Debian、Ubuntu,这些是什么意思
CentOS 7、Debian、Ubuntu 都是基于 Linux 内核的操作系统,它们各自有不同的特性和用途。以下是对它们的详细解释: CentOS 7 CentOS(Community ENTerprise Operating System) 是一个基于开源的 Linux 发行版。CentOS 7 是 CentOS …...

安装Flask
自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 大多数Python包都使用pip实用工具安装,使用Virtualenv创建虚拟环境时会自动安装pip。激活虚拟环境后,pip 所在的路径会被添加…...

OSPF开销、协议优先级、定时器(华为)
#交换设备 OSPF开销值 如果没有定义OSPF接口的开销值,OSPF会根据该接口的带宽自动计算其开销值。 计算公式: 接口开销 带宽参考值 / 接口带宽 (取整数部分,结果小于1时取1)通过改变带宽参考值可以间接改变接口的开…...

接口与实现-常用实用类-Java
接口与实现 接口 使用关键字interface来定义一个接口,接口的定义分为接口声明和接口体,例如: interface Com{ ....... } 接口声明 interface 接口的名字 接口体 接口体中的抽象方法和常量 接口体中所有抽象方法的访问权限一定都是pu…...

【CSS in Depth 2 精译】1.5 渐进式增强
文章目录 1.5 渐进式增强1.5.1 利用层叠规则实现渐进式增强1.5.2 渐进式增强的选择器1.5.3 利用 supports() 实现特性查询启用浏览器实验特性 1.5 渐进式增强 要用好 CSS 这样一门不断发展演进中的语言,其中一个重要的因素就是要与时俱进,及时了解哪些功…...

k8s集群master故障恢复笔记
剔除故障节点 kubectl drain master故障节点 kubectl delete node master故障节点 kubeadm reset rm -rf /etc/kubernetes/manifests mkdir -p /etc/kubernetes/pki/etcd/ 从master其他节点拷 scp /etc/kubernetes/pki/ca.crt ca.key sa.key sa.pub front-proxy-ca.crt …...

昇思25天学习打卡营第5天|网络构建
一、简介: 神经网络模型是由神经网络层和Tensor操作构成的,mindspore.nn提供了常见神经网络层的实现,在MindSpore中,Cell类是构建所有网络的基类(这个类和pytorch中的modul类是一样的作用),也是…...

Python开发日记--手撸加解密小工具(2)
目录 1. UI设计和代码生成 2.运行代码查看效果 3.小结 1. UI设计和代码生成 昨天讨论到每一类算法设计为一个Tab,利用的是TabWidget,那么接下来就要在每个Tab里设计算法必要的参数了,这里我们会用到组件有Label、PushButton、TextEdit、Ra…...

一文看懂TON链
一、背景与起源 The Open Network (TON) 的故事起始于2018年,当时全球知名的即时通讯软件Telegram计划推出自己的区块链平台及加密货币Gram,旨在构建一个既安全又高速的分布式网络,用以支持下一代去中心化应用程序(DApps)和数字资产。然而&a…...

(南京观海微电子)——TFT LCD压合技术
TFT-LCD TFT-LCD open cell后段制程主要指的是将驱动IC和PCB压合至液晶板上,这个制程主要由三个步骤组成: 1.ACF (Anisotropic Conductive Film)的涂布。 在液晶板需要压合驱动IC的地方涂布ACF,ACF又称异方性导电胶膜,特点是上下…...

神经网络实战1-Sequential
链接:https://pytorch.org/docs/1.8.1/generated/torch.nn.Sequential.html#torch.nn.Sequential 完成这样一个网络模型 第一步新建一个卷积层 self.conv1Conv2d(3,32,5)#第一步将33232输出为32通道,卷积核5*5 注意一下:输出通道数等于卷积…...