【再探】设计模式—桥接模式、组合模式及享元模式

 结构型设计模式描述了对象与类之间的关系。适配器模式及装饰器模式主要用于接口适配及功能增强,而桥接模式模式则是为了减少类的数量,组合模式让部分与容器能被客户端统一对待处理,享元模式则是用于节约系统内存,提高系统性能。

1 桥接模式

需求:一个类存在多个纬度,且每个纬度都需要独立进行扩展。例如,Coffee类,它有尺寸及口味两个纬度,这两个纬度有不同的扩展,比如有大杯、小杯,加糖及不加糖。 而且后续这两个纬度可能还会有新的扩展。

1.1 桥接模式介绍

将抽象部分与其实现部分分离,使得它们可以独立地变化。

图 桥接模式 UML

public class BridgePattern {public static void main(String[] args) {TasteImplementor[] tasteArray = {new SugarTasteImplementor(),new SugarTasteImplementor()};for (int i = 0; i < tasteArray.length; i++) {for (int j = 0; j < 2; j++) {CoffeeAbstraction coffee = i == 0 ? new BigCoffee(tasteArray[i]) : new SmallCoffee(tasteArray[i]);coffee.order();}}}private static abstract class CoffeeAbstraction {protected TasteImplementor tasteImplementor;public CoffeeAbstraction(TasteImplementor tasteImplementor) {this.tasteImplementor = tasteImplementor;}abstract String size();void order() {System.out.println(size() + tasteImplementor.taste() + "咖啡");}}private static class BigCoffee extends CoffeeAbstraction{public BigCoffee(TasteImplementor tasteImplementor) {super(tasteImplementor);}@OverrideString size() {return "大杯";}}private static class SmallCoffee extends CoffeeAbstraction {public SmallCoffee(TasteImplementor tasteImplementor) {super(tasteImplementor);}@OverrideString size() {return "小杯";}}private interface TasteImplementor {String taste();}private static class SugarTasteImplementor implements TasteImplementor{@Overridepublic String taste() {return "加糖";}}private static class NoSugarTasteImplementor implements TasteImplementor{@Overridepublic String taste() {return "不加糖";}}}

桥接模式

侧重纬度变化,实现部分的接口不一定要和抽象部分接口保持一致。

装饰模式

侧重动态添加或撤销功能,要求装饰类与被装饰类都实现同一接口。

表 桥接模式与装饰模式对比

1.2 优缺点

优点:

  1. 各个纬度可以独立扩展,将类的数量由m * n 变成 m + n。
  2. 符合单一职责原则、开闭原则、里氏替换原则、依赖倒转原则、合成复用原则。

缺点:

  1. 增加系统的理解和设计难度,要求开发者一开始就针对抽象层进行设计与编程。及需要正确识别出系统中两个独立变化的纬度。

2 组合模式

需求:1)系统中具有整体和部分的层次结构,需要通过一种方式忽略整体和部分的差异,客户端可以一致的使用它们。2)一个系统中能分离出叶子和容器对象,而且它们的类型不固定,将来可能需要增加新的类型。

2.1 组合模式描述

组合多个对象形成树形结构,以表示具有“整体-部分”关系的层次结构。对单个对象(叶子对象)和组合对象(容器对象)的使用具有一致性。有称为“部分-整体(Part-Whole)模式”。

图 组合模式 UML

public class CompositePattern {public static void main(String[] args) {FileComponent file1 = new ImageFile("图片1");FileComponent file2 = new ImageFile("图片2");FileComponent folder1 = new Folder("文件夹1");FileComponent folder2 = new Folder("文件夹2");folder1.add(file1);folder2.add(file2);folder2.add(folder1);System.out.println(folder2.findByName("图片1"));System.out.println(folder1.findByName("图片2"));System.out.println(folder2.findByName("文件夹1"));System.out.println(folder1.findByName("文件夹1"));}private static abstract class FileComponent {protected String name;public FileComponent(String name) {this.name = name;}public abstract FileComponent findByName(String fileName);public abstract void add(FileComponent file);public abstract void remove(FileComponent file);public abstract FileComponent getChild(int i);}private static class ImageFile extends FileComponent {public ImageFile(String name) {super(name);}@Overridepublic FileComponent findByName(String fileName) {return name.equals(fileName) ? this : null;}@Overridepublic void add(FileComponent file) {throw new RuntimeException("不支持该操作");}@Overridepublic void remove(FileComponent file) {throw new RuntimeException("不支持该操作");}@Overridepublic FileComponent getChild(int i) {throw new RuntimeException("不支持该操作");}}private static class Folder extends FileComponent {private final List<FileComponent> children = new ArrayList<>();public Folder(String name) {super(name);}@Overridepublic FileComponent findByName(String fileName) {if (name.equals(fileName)) return this;for (FileComponent file : children) {FileComponent item = file.findByName(fileName);if (item != null) return item;}return null;}@Overridepublic void add(FileComponent file) {children.add(file);}@Overridepublic void remove(FileComponent file) {children.remove(file);}@Overridepublic FileComponent getChild(int i) {return i >= children.size() ? null : children.get(i);}}}

2.1.1 透明组合模式

抽象构件Component中声明了所有用于管理成员对象的方法,包括add()、remove()以及getChild()等方法。

优点:叶子和容器对象所提供的方法是一致的,客户端可以相同地对待所有对象。

缺点:不够安全,叶子和容器对象在本质上有区别,add、remove及getChild方法对于叶子对象来说没有意义。如果调用叶子对象的这些方法,在编译阶段不会报错,但在运行阶段可能出错。

2.1.2 安全组合模式

在抽象构件Component中没有声明任何用于管理成员对象的方法(add、remove及getChild等)。而在容器类Composite中声明并实现了这些方法。

优点:安全,对于叶子对象,不可能会被调用这些方法。

缺点:不够透明,客户端不能完全针对抽象编程,必须有区别地对待叶子和容器对象。

2.2 优缺点

优点:

  1. 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次。让客户端忽略了层次的差异,方便对整个层次结构进行控制。
  2. 增加新的容器构件和叶子构件很方便,符合开闭原则。

缺点:

  1. 很难对容器中的构件类型进行限制,比如希望某容器只能有某些特定类型的构件,这需要通过在运行时进行类型检查来实现。

3 享元模式

需求:1)系统中有大量相同或相似的对象。2)对象中大部份状态时非共享的,可以外部化。

3.1 享元模式介绍

使用共享技术来支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都可共享,状态变化很小。

通常使用单例模式来创建这些共享对象。

图 享元模式 UML

public class FlyweightPattern {public static void main(String[] args) {SoldierFactory.simulate(20,10);}private static class SoldierFactory {public static void simulate(int blueNum,int redNum) {int tempBlueNum = blueNum,tempRedNum = redNum;while (tempBlueNum > 0 && tempRedNum > 0) {Soldier blue = BlueSoldier.getInstance();blue.setId(blueNum - tempBlueNum);Soldier red = RedSoldier.getInstance();red.setId(redNum - tempRedNum);boolean confront = blue.confront(red);if (confront) {tempRedNum--;} else {tempBlueNum--;}}System.out.println("最终结果:" + (tempBlueNum > 0 ? BlueSoldier.getInstance().getType() : RedSoldier.getInstance().getType()) + "胜利");}}private static abstract class Soldier {private final Random random = new Random();protected int id;abstract String getType();void setId(int id) {this.id = id;}boolean confront(Soldier opponent) {boolean result = random.nextInt() % 3 == 0;StringBuilder sb = new StringBuilder();sb.append(this);if (result) {sb.append("消灭").append(opponent);} else {sb.append("阵亡");}System.out.println(sb);return result;}@Overridepublic String toString() {return getType() + id;}}private static class BlueSoldier extends Soldier {private BlueSoldier() {}public static Soldier getInstance() {return Holder.instance;}private static class Holder {private static final Soldier instance = new BlueSoldier();}@OverrideString getType() {return "蓝军";}}private static class RedSoldier extends Soldier {private RedSoldier() {}public static Soldier getInstance() {return Holder.instance;}private static class Holder {private static final Soldier instance = new RedSoldier();}@OverrideString getType() {return "红军";}}}

单纯享元模式

所有的具体享元对象类都是可共享的,不存在不可共享的类。

复合享元模式

将一些单纯享元对象使用组合模式加以组合,形成复合享元对象。

这样可以确保这些享元对象具有相同的外部状态。

表 单纯享元模式与复合享元模式

3.2 优缺点

优点:

  1. 极大减少了内存的使用,提高了系统性能。

缺点:

  1. 需要分离内部和外部状态,使系统变得复杂。
  2. 读取外部状态将使得运行时间变长。

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

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

相关文章

52. UE5 RPG 应用自定义FGameplayEffectContext到项目

在前面一篇文章中&#xff0c;我们创建了自定义的FGameplayEffectContext结构体&#xff0c;用于存储所需的内容。在自定义的结构体内&#xff0c;我们主要是为了增加暴击和格挡两个参数&#xff0c;用于后面的UI显示给玩家&#xff0c;让玩家知道当前触发的状态。并且我们还对…

分布式与一致性协议之PBFT算法(一)

PBFT算法 概述 前面提到了拜占庭将军问题之后&#xff0c;有人可能会感到困惑:口信消息型拜占庭问题直接在实际项目中是如何落地的呢&#xff1f;事实上&#xff0c;它很难在实际项目中落地&#xff0c;因为口信消息型拜占庭问题之解是一个非常理论化的算法&#xff0c;没有与…

区块链数据集(一)Xblock

一、Transaction Datasets Ethereum On-chain Data [Dataset] 2021-10TransactionData/Code AvailableEthereum Introduction: This is the dataset of paper “XBlock-ETH: Extracting and Exploring Blockchain Data From Ethereum”. Data / Code Paper CiteDownloads: …

【Python大数据】PySpark

CSDN不支持多个资源绑定&#xff0c;另外两个数据文件下载&#xff1a; 订单数据-json.zip search-log.zip Apache Spark是用于大规模数据(large-scala data)处理的统一(unified)分析引擎 简单来说&#xff0c;Spark是一款分布式的计算框架&#xff0c;用于调度成百上千的服…

5万字带你一文看懂自动驾驶之高精度地图前世今生

在讲解高精度地图之前&#xff0c;我们先把定位这个事情弄清楚&#xff0c;想明白&#xff0c;后面的事情就会清晰很多&#xff0c;自古哲学里面讨论的人生终极问题&#xff0c;无非就三个&#xff0c;我是谁&#xff0c;我从哪里来&#xff0c;我要去哪里&#xff0c;这里的位…

构建智慧设施管理平台:数字化引领未来建筑行业发展

随着城市化进程的不断推进和建筑行业的持续发展&#xff0c;智慧设施管理平台的重要性日益凸显。在这一背景下&#xff0c;构建智慧设施管理平台成为推动建筑行业数字化转型的关键举措。本文将深入探讨智慧设施管理平台的构建与优势&#xff0c;助力建筑企业把握数字化转型的主…

【从零开始学架构 架构基础】二 架构设计的复杂度来源:高性能复杂度来源

架构设计的复杂度来源其实就是架构设计要解决的问题&#xff0c;主要有如下几个&#xff1a;高性能、高可用、可扩展、低成本、安全、规模。复杂度的关键&#xff0c;就是新旧技术之间不是完全的替代关系&#xff0c;有交叉&#xff0c;有各自的特点&#xff0c;所以才需要具体…

openEuler 22.03安装单机版oracle 19c(附录所有patch包)

客户要在OpenEuler 22.0.3 LTS上安装的19.3.0.0 ,在安装到11%的时候报错all_no_orcl错误,我们知道欧拉底层是rhel9,这些错误其实经常接触都知道肯定是各种软件包的版本不对导致的,但是各种依赖太多了也不好解决,最后在官网有所发现: Requirements for Installing Oracle Datab…

【文末附gpt升级方案】探讨当前时机是否适合进入AIGC行业(一)

随着科技的飞速发展&#xff0c;人工智能生成内容&#xff08;AIGC&#xff09;作为新兴的技术领域&#xff0c;正逐步走进公众的视野&#xff0c;并在多个行业展现出巨大的应用潜力。然而&#xff0c;对于创业者、投资者以及希望进入这一领域的专业人士来说&#xff0c;当前时…

2024新零售行业多元化用工报告

来源&#xff1a;君润人力 近期历史回顾&#xff1a;

小米15曝光?可能会要稍微涨价

也许是感受到了智能机市场的逐渐复苏&#xff0c;最近各大手机品牌发售新品的速度明显加快了。从4月份的Redmi、一加&#xff0c;再到5月份一大堆vivo、OPPO新机型的发布。而近日&#xff0c;有关小米14即将发售的消息也是悄咪咪的放了出来。 去年发售的小米14可以说是狠狠地让…

202012青少年软件编程(Python)等级考试试卷(三级)

第 1 题 【单选题】 在Python正则表达式中&#xff0c;用来匹配任意空白字符的是&#xff08; &#xff09;。 A &#x1f612; B :S C :d D &#x1f604; 正确答案:A 试题解析: 第 2 题 【单选题】 在Python正则表达式中&#xff0c;用来匹配任意非数字字符的是&…

双向RNN和双向LSTM

双向RNN和双向LSTM 一、双向循环神经网络BiRNN 1、为什么要用BiRNN 双向RNN&#xff0c;即可以从过去的时间点获取记忆&#xff0c;又可以从未来的时间点获取信息,也就是说具有以下两个特点&#xff1a; 捕捉前后文信息&#xff1a;传统的单向 RNN 只能利用先前的上下文信息…

vue3+ts(<script setup lang=“ts“>)刷新页面后保持下拉框选中效果

效果图&#xff1a; 代码&#xff1a; <template><div class"app-layout"><div class"app-box"><div class"header"><div class"header-left"></div><div class"title">室外智…

scratch列表排序 2024年3月中国电子学会图形化编程 少儿编程 scratch编程等级考试四级真题和答案解析

目录 scratch列表排序 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、p…

Python函数之旅专栏(导航)

Python内置函数(参考版本:3.11.8)AELRabs( )enumerate( )len( )range( )aiter( )eval( )list( )repr( )all( )exec( )locals( )reversed( )anext( )round( )any( ) ascii( )FM  filter( )map( )S float( )max( )set( )Bformat( )memoryview( )setattr( )bin( )frozenset( )…

ArcGI基本技巧-科研常用OLS, GWR, GTWR模型实现

ArcGI基本技巧-科研常用OLS, GWR, GTWR模型实现 OLS,GWR,GTWR回归模型均可以揭示解释变量对被解释变量的影响且可以进行预测。Ordinary Least Squares (OLS)是最小二乘法&#xff0c;Geographically Weighted Regression (GWR)是地理加权回归&#xff0c;Geographically and T…

Unity射击游戏开发教程:(18)添加弹药计数+补充弹药

添加简单的弹药计数 我将讨论如何向游戏中添加简单的弹药计数。这将包括在 HUD 中添加弹药计数器,当弹药达到 0 时,文本会将颜色更改为红色以提醒玩家。另外,当弹药数为0时,玩家将无法再射击。让我们深入了解吧! 在播放器脚本中我们需要添加一些变量。我们将创建两个公共整…

详细分析Python中的win32com(附Demo)

目录 前言1. 基本知识2. Excel3. Word 前言 对于自动化RPA比较火热&#xff0c;相应的库也比较多&#xff0c;此文分析win32com这个库&#xff0c;用于操作office 1. 基本知识 Win32com 是一个 Python 模块&#xff0c;是 pywin32 扩展的一部分&#xff0c;允许 Python 代码…

C语言如何删除表中指定位置的结点?

一、问题 如何删除链表中指定位置的结点&#xff1f; 二、解答 删除链表中指定的结点&#xff0c;就像是排好队的⼩朋友⼿牵着⼿&#xff0c;将其中⼀个⼩朋友从队伍中分出来&#xff0c;只需将这个⼩朋友的双⼿从两边松开。 删除结点有两种情况&#xff1a; &#xff08;1&am…