【设计模式】聊聊模板模式

原理和实现

设计模式的原理和实现是比较简单的,难的是掌握具体的应用场景和解决什么问题。而模板模式是为来解决复用和拓展两个问题。
模板模式在一个方法中定义好一个算法框架,然后将某些步骤推迟到子类中实现,子类可以在不修改父类流程的时候,实现自己的特有逻辑。

具体code如下。ZkLock定义顶层接口设计,ZkAbstractTemplateLock 实现了基础功能,但是具体的wait和try的流程是固定在ZKlock抽象类中,子类只能根据自己的特性实现对应的方法。


public interface ZkLock {/**** 获取锁*/public void zkLock();/**** 释放锁*/public void zkUnLock();}public abstract class ZkAbstractTemplateLock implements ZkLock {private static final String ZKSERVER = "192.168.58.138:2181";private static final int TIME_OUT = 45 * 100;public static final String zkLockPath = "/zkLock";public static CountDownLatch countDownLatch = null;ZkClient zkClient =  new ZkClient(ZKSERVER,TIME_OUT);@Overridepublic void zkLock() {//模板设计方法 抽象定义在父类中,具体实现由子类来实现if (tryLock()){System.out.println(Thread.currentThread().getName()+"\t 拿到锁");}else {waitLock();zkLock();}}//将公共的代码抽取到父类中public abstract void waitLock();/**** 尝试获取锁* @return*/public abstract boolean tryLock();@Overridepublic void zkUnLock() {if(zkClient!=null){zkClient.close();//关闭客户端 node节点自动删除}System.out.println(Thread.currentThread().getName()+"\t 释放锁成功");System.out.println();}
}public class ZkDistributedLock extends ZkAbstractTemplateLock {@Overridepublic void waitLock() {IZkDataListener iZkDataListener = new IZkDataListener() {@Overridepublic void handleDataChange(String s, Object o) throws Exception {}//数据被修改 监听Watch@Overridepublic void handleDataDeleted(String s) throws Exception {//如果节点数据删除了 那么countDownLatch减一countDownLatch.countDown();}};//在某一个节点上监听事件zkClient.subscribeDataChanges(zkLockPath,iZkDataListener);//当不为nullif (zkClient.exists(zkLockPath)){countDownLatch = new CountDownLatch(1);//计数1 为0返回try {//一旦节点被删除 触发事件就执行countDownLatch.await();} catch (InterruptedException e) {e.fillInStackTrace();}}//解除监听器zkClient.unsubscribeDataChanges(zkLockPath,iZkDataListener);}@Overridepublic boolean tryLock() {try {zkClient.createEphemeral(zkLockPath);return true;}catch (Exception e){return false;}}
}

复用

java inputstream

inputstream 定义了read的基础读取方法,但是也暴露了一个子类可以定制的抽象方法。

public abstract class InputStream implements Closeable {public int read(byte b[], int off, int len) throws IOException {if (b == null) {throw new NullPointerException();} else if (off < 0 || len < 0 || len > b.length - off) {throw new IndexOutOfBoundsException();} else if (len == 0) {return 0;}int c = read();if (c == -1) {return -1;}b[off] = (byte)c;int i = 1;try {for (; i < len ; i++) {c = read();if (c == -1) {break;}b[off + i] = (byte)c;}} catch (IOException ee) {}return i;}public abstract int read() throws IOException;}

java abstractList

abstract class AbstractList 定义了addAll() , 但是留除了一个拓展点给子类,如果子类不实现的话,不能使用。

public boolean addAll(int index, Collection<? extends E> c) {rangeCheckForAdd(index);boolean modified = false;for (E e : c) {add(index++, e);modified = true;}return modified;}public void add(int index, E element) {throw new UnsupportedOperationException();}//arraylist实现了自己的 addpublic void add(int index, E element) {rangeCheckForAdd(index);ensureCapacityInternal(size + 1);  // Increments modCount!!System.arraycopy(elementData, index, elementData, index + 1,size - index);elementData[index] = element;size++;}

拓展

java servlet

在这里插入图片描述
拓展点这里其实是指框架的拓展点,即用户在不修改框架源码的时候,只需要按照框架提高的类进行拓展就可以实现自己的业务逻辑。

小结

模板模式的本质定义一个框架流程,具体的拓展点可以子类进行实现。具体的功能是复用和拓展,复用是指的是,所有的子类可以复用父类中提供的模板方法的代码,拓展是框架通过模板模式提供功能拓展点,用户不修改框架源码的情况下,基于拓展点就可以实现功能。

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

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

相关文章

qsort使用举例和qsort函数的模拟实现

qsort使用举例 qsort是C语言中的一个标准库函数&#xff0c;用于对数组或者其他数据结构中的元素进行排序。它的原型如下&#xff1a; void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 我们可以去官网搜来看一看&#xff1a;…

golang学习笔记——生成随机整数的函数Int31n

介绍 rand.31n()函数是Golang标准库中用来生成介于0到n之间的随机整数的函数。其中n是指定的范围&#xff0c;可以是任意正整数。该函数的具体实现方式是在go语言内部使用C语言的随机数生成函数来生成随机数。 具体来说&#xff0c;rand.Int31n()函数的参数n表示要生成的随机…

Ubuntu20.04安装Beyond Compare 4.4.7

参考链接&#xff1a; 1.Ubuntu20.04 Beyond Compare 4.3.7 安装 2.Ubuntu20.04安装Beyond Compare 4.3.7

MySQL 定时计划任务 事件的使用

目录 查看事件是否开启 开启事件 1&#xff09;通过设置全局参数修改 2&#xff09;更改配置文件 MySQL如何创建并执行事件&#xff1f; 例 1 MySQL查看事件状态信息 MySQL修改和删除事件 例 1 例 2 删除事件 例 3 在数据库管理中&#xff0c;经常要周期性的执行某…

lxml基本使用

lxml是python的一个解析库&#xff0c;支持HTML和XML的解析&#xff0c;支持XPath解析方式&#xff0c;而且解析效率非常高 XPath&#xff0c;全称XML Path Language&#xff0c;即XML路径语言&#xff0c;它是一门在XML文档中查找信息的语言&#xff0c;它最初是用来搜寻XML文…

【C/PTA】数组进阶练习(二)

本文结合PTA专项练习带领读者掌握数组&#xff0c;刷题为主注释为辅&#xff0c;在代码中理解思路&#xff0c;其它不做过多叙述。 目录 7-1 字符串逆序7-2 字符串替换7-3 统计字符出现次数7-4 IP地址转换7-1 删除重复字符7-2 说反话-加强版7-3 数组-回文串7-4 数组-无聊的菇菇…

2024全网最新最全的Pytest接口自动化测试框架教程

pytest编写的规则&#xff1a; 1、测试文件以test_开头&#xff08;以_test结尾也可以&#xff09; 2、测试类以Test开头&#xff0c;并且不能带有__init__方法 3、测试函数以test_开头 4、断言必须使用assert pytest.main([-s,-v]) &#xff1a;用来执行测试用例 -s 打印prin…

卷积神经网络(CNN)天气识别

文章目录 前期工作1. 设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;我的环境&#xff1a; 2. 导入数据3. 查看数据 二、数据预处理1. 加载数据2. 可视化数据3. 再次检查数据4. 配置数据集 三、构建CNN网络四、编译五、训练模型六、模型评估 前期工作 1. 设置GP…

11.10 校招 实习 内推 面经

绿*泡*泡&#xff1a; neituijunsir 交流裙 &#xff0c;内推/实习/校招汇总表格 1、校招丨海康机器人2024校招3大类岗位补录&#xff08;内推&#xff09; 校招丨海康机器人2024校招3大类岗位补录&#xff08;内推&#xff09; 2、校招&实习 | 华为数据存储研究部招聘…

SELinux零知识学习十九、SELinux策略语言之类型强制(4)

接前一篇文章&#xff1a;SELinux零知识学习十八、SELinux策略语言之类型强制&#xff08;3&#xff09; 二、SELinux策略语言之类型强制 2. 类型、属性和别名 &#xff08;4&#xff09;别名 别名是引用类型时的一个备选的名字&#xff0c;能够使用类型名的地方就可以使用别…

EEPROM与Flash的区别

EEPROM与Flash的区别 EEPROMEEPROM内部功能框图实现写入数据内部结构存储管在充电或放电状态下有着不同的阈值电压 问题点EEPROM是如何失效的呢&#xff1f;为何EEPROM不能做大呢&#xff1f; ------------------------------------------------------------------------------…

HTTP请求详解

HTTP请求格式 请求报文通常包含以下部分: 请求行(Request Line): 包括请求方法、请求的URL和协议版本。 示例:GET /index.html HTTP/1.1 请求头(Request Headers): 包含了一系列的键值对,用来描述客户端请求的相关信息,比如Accept(告诉服务器客户端能够处理的MIME类型…

Java多线程(3)

Java多线程(3) 深入剖析Java线程的生命周期&#xff0c;探秘JVM的线程状态&#xff01; 线程的生命周期 Java 线程的生命周期主要包括五个阶段&#xff1a;新建、就绪、运行、阻塞和销毁。 **新建&#xff08;New&#xff09;&#xff1a;**线程对象通过 new 关键字创建&…

tamarin运行

首先我们找到安装tamarin的文件位置&#xff0c;找到以后进入该文件夹下 ubuntuubuntu:~$ sudo find / -name tamarin-prover /home/linuxbrew/.linuxbrew/var/homebrew/linked/tamarin-prover /home/linuxbrew/.linuxbrew/Cellar/tamarin-prover /home/linuxbrew/.linuxbrew/…

mac下vue-cli从2.9.6升级到最新版本

由于mac之前安装了 vue 2.9.6 的版本&#xff0c;现在想升级到最新版本&#xff0c;用官方给的命令&#xff1a; npm uninstall vue-cli -g 发现不行。 1、究其原因&#xff1a;从vue-cli 3.0版本开始原来的npm install -g vue-cli 安装的都是旧版&#xff0c;最高到2.9.6。安…

基于Netty实现的简单聊天服务组件

目录 基于Netty实现的简单聊天服务组件效果展示技术选型&#xff1a;功能分析聊天服务基础设施配置&#xff08;基于Netty&#xff09;定义组件基础的配置&#xff08;ChatProperties&#xff09;定义聊天服务类&#xff08;ChatServer&#xff09;定义聊天服务配置初始化类&am…

后端接口错误总结

今天后端错误总结&#xff1a; 1.ConditionalOnExpression(“${spring.kafka.exclusive-group.enable:false}”) 这个标签负责加载Bean&#xff0c;因此这个位置必须打开&#xff0c;如果这个标签不打开就会报错 问题解决&#xff1a;这里的配置在application.yml文件中 kaf…

数据结构之双向带头循环链表函数功能实现与详细解析

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 数据结构初阶 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂。 目录 1.前言 2.带头双…

Linux Docker图形化工具Portainer如何进行远程访问?

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

Flutter最新稳定版3.16 新特性介绍

Flutter 3.16 默认采用 Material 3 主题&#xff0c;Android 平台预览 Impeller&#xff0c;DevTools 扩展等等 欢迎回到每季度一次的 Flutter 稳定版本发布&#xff0c;这次是 Flutter 3.16。这个版本将 Material 3 设为新的默认主题&#xff0c;为 Android 带来 Impeller 预览…