设计模式⑤ :一致性

一、前言

有时候不想动脑子,就懒得看源码又不像浪费时间所以会看看书,但是又记不住,所以决定开始写"抄书"系列。本系列大部分内容都是来源于《 图解设计模式》(【日】结城浩 著)。该系列文章可随意转载。

二、Composite 模式(组合模式)

Composite 模式 :容器与内容的一致性

1. 介绍

能够使容器与内容具有一致性,创造出具有递归结构的模式就是 Composite 模式(组合模式)。


Composite 模式中登场的角色

  • Leaf (树叶):表示“内容”的角色,在该角色中不能放入其他角色。
  • Composite(复合物):表示容器的角色,可以在其中放入 Leaf 角色和 Composite 角色。
  • Component :使用 Leaf 和 Composite 角色具有一致性的角色。Component 角色是 Leaf 角色和 Composite角色的父类。
  • Client :使用 Composite 模式的角色。

类图如下:

在这里插入图片描述


Demo如下:

// 条目,父级接口
public interface Entry {/*** 获取文件名** @return*/String getName();/*** 获取文件大小** @return*/int getSize();/*** 添加目录,默认抛出异常** @param entry* @return*/default Entry addEntry(Entry entry){throw new RuntimeException();}/*** 打印目录*/default void printList() {printList("");}/*** 打印目录** @param prefix*/default void printList(String prefix){System.out.println(prefix + "/" + thisPath());}default String thisPath() {return getName() + "(" + getSize() + ")";}
}// 文件类型
public class File implements Entry {private String name;private int size;public File(String name, int size) {this.name = name;this.size = size;}@Overridepublic String getName() {return name;}@Overridepublic int getSize() {return size;}@Overridepublic void printList(String prefix) {System.out.println(prefix + "/" + thisPath());}
}// 文件夹类型
public class Directory implements Entry {private String name;private List<Entry> entries = Lists.newArrayList();public Directory(String name) {this.name = name;}@Overridepublic String getName() {return name;}@Overridepublic int getSize() {return entries.stream().mapToInt(Entry::getSize).sum();}@Overridepublic Entry addEntry(Entry entry) {entries.add(entry);return this;}@Overridepublic void printList(String prefix) {System.out.println(prefix + "/" + thisPath());entries.forEach(entry -> entry.printList(prefix + "/" + name));}
}// main 方法:输出每个文件夹下的目录及大小
public class CompositeDemoMain {public static void main(String[] args) {Entry rootDir = new Directory("root");Entry binDir = new Directory("bin");Entry tmpDir = new Directory("tmp");Entry usrDir = new Directory("usr");Entry hanakoDir = new Directory("hanako");usrDir.addEntry(hanakoDir);rootDir.addEntry(binDir);rootDir.addEntry(tmpDir);rootDir.addEntry(usrDir);hanakoDir.addEntry(new File("memo.tex", 10));binDir.addEntry(new File("vi", 1000));binDir.addEntry(new File("latex", 2000));rootDir.printList();}
}

输出如下:
在这里插入图片描述


以上面的例子为例, Entry 可能是 File 的实现,也可能是 Directory 的实现,但无论是哪种实现,都可以通过 getSize 得到他的大小。这就是 Composite 模式的特征:容器与内容的一致性。

2. 应用

暂时没想到



个人使用:该部分内容是写给自己看的,帮助自身理解,因此就不交代项目背景了,读者请自行忽略(◐ˍ◑)

  • 项目A中,需要对敏感词构建出一个树状图,以此进行脱敏处理。构建出的敏感词数据结构即是一个树状图结构。具体逻辑这里不再写出,类似下图(详参 https://mp.weixin.qq.com/s/7Rm87J7PJcA8KKwM8m1yVQ):
    在这里插入图片描述

3. 总结

通常来说,树结构的数据结构都适用于 Composite 模式。
扩展思路:

  • 多个和单个的一致性 :使用 Composite 模式可以使容器与内容具有一致性,也可以称其为多个和单个的一致性,即将多个对象结合在一起,当做一个对象进行处理。通常来说树结构的数据结构都适用于 Composite 模式。如

相关模式:

  • Command 模式:使用 Command 模式编写宏命令时使用了 Composite 模式
  • Visitor 模式:可以使用 Visitor 模式访问 Composite 模式中的递归结构
  • Decorator 模式:Composite 模式通过 Component 角色使容器(Composite 角色) 和 内容 (Leaf 角色)具有一致性。Decorator 模式使装饰框和内容具有一致性。

三、Decorator 模式(装饰器模式)

Decorator 模式 :装饰边框与被装饰物的一致性

1. 介绍

Decorator 模式即为对象添加装饰的设计模式。如一个蛋糕,只涂上奶油就是奶油蛋糕,如果再加上草莓就是草莓奶油蛋糕,不过不管加了什么,其核心都是蛋糕。装饰器模式与之类似,不断地为对象添加装饰的模式即为装饰器模式。


登场的角色:

  • Component :增加功能时的核心角色。
  • ConcreteComponent :该角色是实现了 Component 角色所定义的接口的具体角色。
  • Decorator (装饰物):该角色具有与 Component 角色相同的接口,在它内部保存了被装饰的对象(Component 角色)。Decorator 角色知道自己要装饰的角色。
  • ConcreteDecorator (具体的装饰物):该角色是具体的 Decorator 角色。

类图如下:
在这里插入图片描述

2. 应用

  • Dubbo 在进行服务间调用时会通过 Invoker 来调用,如下图,从 Invoker 的调用过程也可以看出 Invoker 是通过装饰器模式修饰的。
    在这里插入图片描述

  • Java IO 包中IO类,如下可以自由组合出很多IO操作。

          Reader reader = new FileReader("/demo.txt");Reader reader = new BufferedReader(new FileReader("/demo.txt"));Reader reader = new LineNumberReader(new BufferedReader(new FileReader("/demo.txt")));
    


个人使用:该部分内容是写给自己看的,帮助自身理解,因此就不交代项目背景了,读者请自行忽略(◐ˍ◑)

  • 项目 A 中,需要对外提供脱敏后的数据,但是程序内部使用未脱敏的数据,则可以通过装饰器模式,构建一个脱敏的实现来对外提供数据,如下:FullDataHolder 是程序内部使用未脱敏的数据,DesensitizationDataHolder 则对 FullDataHolder 进行了装饰,对外提供脱敏后的数据。

    // 数据持有接口
    public interface DataHolder {/*** 获取数据* @return*/String getData();
    }// 全量数据持有者
    public class FullDataHolder implements DataHolder {@Overridepublic String getData() {return "全量敏感数据";}
    }// 脱敏数据持有者
    public class DesensitizationDataHolder implements DataHolder{/*** 数据持有者*/private DataHolder dataHolder;public DesensitizationDataHolder(DataHolder dataHolder) {this.dataHolder = dataHolder;}@Overridepublic String getData() {return dataHolder.getData().replace("敏感", "**");}
    }public class DemoMain {public static void main(String[] args) {DataHolder dataHolder = new FullDataHolder();System.out.println(dataHolder.getData());// 使用 DesensitizationDataHolder 对 FullDataHolder进行装饰,输出脱敏后的数据DataHolder desensitizationDataHolder = new DesensitizationDataHolder(dataHolder);System.out.println(desensitizationDataHolder.getData());}
    }
    

    输出如下:

    在这里插入图片描述

3. 总结

扩展思路:

  • 接口的透明性 : 装饰边框与被装饰物具有一致性,因为被装饰物的接口并不会因为被装饰而被隐藏起来。
  • 在不改变被装饰物的前提下增加功能 :由于装饰边框和被装饰物的暴露接口相同,我们可以进行多次装饰,越装饰功能则越多,并且不需要对被装饰的类做任何处理。即实现了不修改被装饰的类即可增加功能。
  • 可以动态地增加功能 :Decorator 模式中使用了委托,使得类之间形成了弱关联关系,因此在不改变框架代码的情况下就可以生成一个与其他对象具有不同关系的新对象。
  • 只需要一些装饰物即可添加许多功能 :装饰边框可以提供多个,即使每个装饰边框增加的功能很简单,但是可以通过多个装饰边框的嵌套来增加更复杂的功能。

装饰器模式的缺点在于:如果装饰器的增加的功能较小,可能会导致程序中增加许多功能类似的很小的类。


相关设计模式:

  • Adapter 模式 :Decorator 模式可以在不改变被装饰物的接口的前提下,为被装饰物添加边框。Adapter 模式适用于两个不同的接口。
  • Strategy 模式 :Decorator 模式可以像改变装饰物的边框或是为被装饰物添加多重边框那样,来增加类的功能。Strategy 模式通过整体地替换算法来改变类的功能。

参考文章

https://mp.weixin.qq.com/s/7Rm87J7PJcA8KKwM8m1yVQ

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

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

相关文章

【Docker】Linux中Docker镜像结构及自定义镜像,并且上传仓库可提供使用

目录 一、镜像结构 1. 基本结构 2. 常用命令 二、自定义镜像 1. 基本镜像 2. 进阶镜像 3. 完善镜像 三、镜像上传仓库 每篇一获 一、镜像结构 自定义 Docker 镜像有很多用途&#xff0c;以下是一些主要的应用场景&#xff1a; 一致性环境&#xff1a;通过自定义镜像&a…

Gauss消去法(C++)

文章目录 算法描述顺序Gauss消去法列选主元Gauss消去法全选主元Gauss消去法Gauss-Jordan消去法 算法实现顺序Gauss消去法列选主元Gauss消去法全选主元Gauss消去法列选主元Gauss-Jordan消去法 实例分析 Gauss消去法是求解线性方程组较为有效的方法, 它主要包括两个操作, 即消元和…

正则表达式Regex

是什么&#xff1a;一句话&#xff0c;正则表达式是对字符串执行模式匹配的技术。 从一段字符串中提取出所有英文单词、数字、字母和数字。 如果采用传统方法&#xff1a;将字符串的所有字符分割成单个&#xff0c;根据ASCII码判断&#xff0c;在一定范围内就是字母&#xff…

pymssql 报错误解决办法:20002, severity 9

错误 解决办法 python3.6&#xff0c;安装pymssql低版本&#xff08;pymssql-2.1.5-cp36-cp36m-win32.whl&#xff09;

【教3妹学编程-算法题】构造限制重复的字符串

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开森。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;最近一周都是大晴天&#xff0c;艳阳高照 2哥&#xff1a;是啊&am…

相比其他关系型数据库,亚信安慧AntDB JDBC驱动特性有哪些不同之处

关键字&#xff1a;JDBC&#xff0c;双引擎语法&#xff0c;安全加强&#xff0c;批量更新 使用Java语言进行各类应用程序的快速开发成为目前比较主要且流行的开发方式。JDBC是 Java 语言中用来连接和操作关系型数据库的 API&#xff0c;在业务程序与关系型数据库通信时&#…

一文了解Git(所有命令)附带图片

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 其他…

机器学习算法理论:线性回归

线性回归 回归的理论解释&#xff1a;回归分析是确定两种或两种以上变数间相互依赖的定量关系的一种统计分析方法。按照自变量和因变量之间的关系类型&#xff0c;可分为线性回归分析和非线性回归分析。 如果在回归分析中&#xff0c;只包括一个自变量和一个因变量&#xff0c;…

【Linux】Linux基础之权限

目录 一、Linux中的用户1.1 用户之间的身份切换1.2 指令提权 二、权限管理2.1 文件权限2.2 权限操作2.3 chown和chgrp 三、文件类型四、目录文件的权限操作五、权限掩码六、粘滞位 一、Linux中的用户 Linux中主要有两种用户&#xff1a; root&#xff0c;超级用户非root&…

Netfilter 是如何工作的(六):连接跟踪信息的入口创建(in)和出口确认(confirm)

Articles (gitee.io) IPtables-朱双印博客 (zsythink.net) 在 Netfilter 是如何工作的(五) 中连接跟踪信息使用的创建-确认机制的 Netfilter在报文进入系统的入口处&#xff0c;将连接跟踪信息记录在报文上&#xff0c;在出口进行confirm.确认后的连接信息 本文以一个本机上送…

【MATLAB】CEEMDAN+FFT+HHT组合算法

代码原理 集成经验模态分解&#xff08;CEEMDAN&#xff09;是一种信号处理方法&#xff0c;旨在将非线性和非平稳信号分解为本质模态函数&#xff08;IMF&#xff09;。这种方法通过对信号进行多轮迭代&#xff0c;结合了噪声干扰的累计退化&#xff0c;从而更好地处理了信号…

关于React你必须知道的3个错误用法。

1. 你知道如何使用“&&”吗? 在React程序中,我经常使用“&&”运算符来决定是否显示内容,如下所示: 我的组长: “你不知道&&运算符的特性吗?当请求还没有成功返回时,会直接渲染“0”。” 我并不信服, 因为我一直都是这样编写代码,从未出过错。为了…

计算机网络技术-2022期末考试解析

【前言】 这是计算机网络技术这门课&#xff0c;感觉和计网还是有不一样的&#xff0c;但也有能做的&#xff0c;把能做的做了。 一、单项选择题&#xff08;每题2分&#xff0c;共20分&#xff09; 1. 用于测试两台计算机连通状况的命令是 。 ( ) A. cmd B. ping C. ipconf…

Java副本的概念

在Java中&#xff0c;"副本"&#xff08;copy&#xff09;一词可以用于描述不同的概念&#xff0c;具体取决于上下文。以下是两个常见的用法&#xff1a; 对象的副本&#xff1a;在Java中&#xff0c;当你创建一个对象并将其赋值给另一个变量时&#xff0c;实际上是创…

配置CentOS系统以支持静态HTTP服务

CentOS是一个流行的Linux发行版&#xff0c;广泛应用于服务器环境。要配置CentOS系统以支持静态HTTP服务&#xff0c;您可以按照以下步骤进行操作&#xff1a; 安装Web服务器软件&#xff1a;CentOS自带了Apache HTTP服务器软件&#xff0c;您可以使用以下命令安装它&#xff1…

Go 知多少?

作为一名已接触过其他语言的开发&#xff0c;再去学习一门新语言可比之前轻松不少&#xff0c; 语言之间存在很多相似点&#xff0c;但是新语言也有自己的不同点&#xff0c;通常我会先了解它与其他语言常遇到的不同点有哪些&#xff0c; 使自己先能够上手编写基础程序&#…

Java多线程:初识多线程!左手画方,右手画圆

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、线程与进程二、创建线程方法1、继承Thread类2、实现Runnable接口3、两者区别4、举个栗子5、简洁写法Ⅰ、Thread匿名内部类写…

DNS 正/反向解析 主从复制 分离解析

一 DNS概念它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便地访问互联网 每一台 DNS 服务器都只负责管理一个有限范围 根域: 全球根服务器节点只有13个,10个在美国&#xff0c;1个荷兰&#xff0c;1个瑞典&#xff0c;1个日本 一级域名&#xff…

【已解决】C语言实现多线程的同步与异步

说真的写了这篇博文时&#xff0c;才知道c语言本身不支持多线程&#xff0c;而是一些windowsapi让c语言拥有多线程的能力&#xff0c;那下面内容就以打开对话框为例&#xff0c;展现如何实现多线程的同步与异步。 文章目录 问题起源c语言多线程同步方案c语言多线程异步方案总结…

Typora使用及Markdow学习笔记1

编程如画&#xff0c;我是panda&#xff01; 最近有在学习Markdown&#xff0c;所以这次分享一下我的Markdown学习笔记 目录 前言 一、标题 二、段落 1.换行 2.分割线 三、文字显示 1.字体 2.上下标 四、列表 1.无序列表 2.有序列表 3.任务列表 五、区块 六、代…