当前位置: 首页 > news >正文

设计模式解析:组合模式与装饰模式

组合模式

动机

在软件开发中,处理整体与部分之间的关系时,组合模式是常用的设计选择。此模式将对象组织为树形结构,让客户端能统一对待单个对象和组合对象,简化操作。

结构

组合模式包含以下角色:

  • Component(抽象构件):定义叶子和容器对象的共同接口,提供一些默认行为。
  • Leaf(叶子):表示树的叶子节点,无法再分解。
  • Composite(容器):表示可以包含其他叶子或容器节点的容器对象。
  • Client(客户端):通过Component接口对组合对象进行操作。

示例代码

// 抽象构件
interface Component {void operation();
}// 叶子节点
class Leaf implements Component {public void operation() {// 叶子节点的实现}
}// 容器节点
class Composite implements Component {private List<Component> children = new ArrayList<>();public void add(Component component) {children.add(component);}public void remove(Component component) {children.remove(component);}public void operation() {for (Component component : children) {component.operation();}}
}// 客户端代码
Component leaf1 = new Leaf();
Component leaf2 = new Leaf();
Composite composite = new Composite();
composite.add(leaf1);
composite.add(leaf2);
composite.operation();

优缺点

优点:

  • 统一处理单个对象与组合对象,简化客户端逻辑。
  • 易于扩展和修改整体结构,符合开闭原则。

缺点:

  • 增加系统复杂性,需理解组合模式的概念。

装饰模式

动机

在软件开发中,经常需要给对象添加额外功能而不修改其原始类。传统的继承方式容易导致类的增多,且静态继承关系无法在运行时动态改变。装饰模式通过组合和委托的方式灵活地为对象添加功能,同时保持原有接口及行为。

结构

装饰模式包含以下角色:

  • Component(抽象构件):定义原始类与装饰类的公共接口,可以是抽象类或接口。
  • ConcreteComponent(具体构件):实现Component接口的原始类,可以被装饰。
  • Decorator(抽象装饰类):实现Component接口,并持有一个Component引用,通过构造函数或setter方法注入。
  • ConcreteDecorator(具体装饰类):继承Decorator类,通过调用父类的方法扩展对象功能。

示例代码

// 抽象构件
interface Component {void operation();
}// 具体构件
class ConcreteComponent implements Component {public void operation() {// 具体实现}
}// 抽象装饰类
class Decorator implements Component {private Component component;public Decorator(Component component) {this.component = component;}public void operation() {component.operation();}
}// 具体装饰类
class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) {super(component);}public void operation() {super.operation();// 扩展功能}
}// 客户端代码
Component component = new ConcreteDecorator(new ConcreteComponent());
component.operation();

在示例中,通过装饰模式动态添加功能而不需修改原始类。结合组合和委托,可在运行时灵活添加、删除功能,并支持多层嵌套。

优缺点

优点:

  • 灵活地动态添加功能,比继承更优。
  • 支持嵌套装饰,实现更复杂功能扩展。
  • 遵循开闭原则,无需修改原始类即可扩展功能。

缺点:

  • 增加类数量,可能导致类膨胀。
  • 装饰链过长时,影响执行效率。

变形金刚实例中的装饰模式

动机

在变形金刚中,每个角色都有不同形态,比如机器人和车辆。我们希望在运行时动态切换这些形态,而不改变其原有行为。

结构

变形金刚实例包含以下角色:

  • Transformable(可变形接口):定义变形方法。
  • Transformer(变形金刚抽象类):实现可变形接口,提供默认行为。
  • CarTransformer(车辆变形金刚):实现车辆形态的变形方法。
  • RobotTransformer(机器人变形金刚):实现机器人形态的变形方法。

示例代码

// 可变形接口
interface Transformable {void transform();
}// 变形金刚抽象类
abstract class Transformer implements Transformable {protected String name;public Transformer(String name) {this.name = name;}public void transform() {System.out.println(name + " 正在变形...");}
}// 车辆变形金刚类
class CarTransformer extends Transformer {public CarTransformer(String name) {super(name);}public void transform() {super.transform();System.out.println(name + " 变身为车辆。");}
}// 机器人变形金刚类
class RobotTransformer extends Transformer {public RobotTransformer(String name) {super(name);}public void transform() {super.transform();System.out.println(name + " 变身为机器人。");}
}// 客户端代码
Transformable bumblebee = new CarTransformer("大黄蜂");
bumblebee.transform();Transformable optimusPrime = new RobotTransformer("擎天柱");
optimusPrime.transform();

在示例中,使用装饰模式实现变形金刚实例。Transformer类是抽象类,实现可变形接口并提供默认变形方法,CarTransformer和RobotTransformer分别实现车辆和机器人形态的变形。这样可在运行时动态切换形态,而无需修改原有类结构,实现灵活及扩展性。

优缺点

优点:

  • 动态切换对象形态,提高灵活性。
  • 在运行时增减功能,无需修改原有结构。
  • 支持多层嵌套装饰,实现复杂功能。

缺点:

  • 增加类数量,可能导致类膨胀。
  • 装饰链过长时,可能影响执行效率。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • php7.4二进制安装-contos7
  • HoloLens 和 Unity 空间坐标系统 Coordinate systems
  • 信号signal与信号量semaphore的区别
  • 基于STM32开发的智能植物浇水系统
  • 音视频相关知识
  • 算法的学习笔记—链表中倒数第 K 个结点(牛客JZ22)
  • 激光雷达点云投影到图像平面
  • CSS方向选择的艺术:深入探索:horizontal和:vertical伪类
  • Ansible可视化管理之web界面集成使用探究(未完待续)
  • 2024年杭州市网络与信息安全管理员(网络安全管理员)职业技能竞赛的通知
  • 【STM32嵌入式系统设计与开发拓展】——14_定时器之输入捕获
  • 用关系图和示例解释异步/等待
  • c++动态数组new和delete
  • kubernetes k8s Daemonset 控制器 原理 讲解 配置
  • 微前端架构下的多租户支持:实现与最佳实践
  • [译]CSS 居中(Center)方法大合集
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • centos安装java运行环境jdk+tomcat
  • gulp 教程
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • js作用域和this的理解
  • Octave 入门
  • Otto开发初探——微服务依赖管理新利器
  • PAT A1017 优先队列
  • PHP 小技巧
  • rc-form之最单纯情况
  • Xmanager 远程桌面 CentOS 7
  • 创建一种深思熟虑的文化
  • 反思总结然后整装待发
  • 聊聊directory traversal attack
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 微信小程序设置上一页数据
  • 在electron中实现跨域请求,无需更改服务器端设置
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • #include<初见C语言之指针(5)>
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (~_~)
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (回溯) LeetCode 46. 全排列
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (译)2019年前端性能优化清单 — 下篇
  • (转)Windows2003安全设置/维护
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • ./configure、make、make install 命令
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .NET Framework 服务实现监控可观测性最佳实践
  • .NET 常见的偏门问题
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?