设计模式之装饰模式解析

装饰模式
1)概述
1.定义

动态地给一个对象增加一些额外的职责,在增加对象功能时,装饰模式比生成子类实现更为灵活。

2.作用

装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。

3.结构图

在这里插入图片描述

4.角色
  • Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。

  • ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。

  • Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现,它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。

  • ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责,每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

5.代码案例

抽象装饰类

public class Decorator implements Component {//维持一个对抽象构件对象的引用private Component component;//注入一个抽象构件类型的对象public Decorator(Component component){this.component = component;}public void operation() {//调用原有业务方法component.operation();}
}

注意:在Decorator中并未实现operation()方法,而只是调用原有component对象的operation()方法,它没有真正实施装饰,而是提供一个统一的接口,将具体装饰过程交给子类完成。

具体装饰类

public class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) {super(component);}public void operation() {super.operation();  //调用原有业务方法addedBehavior();  //调用新增业务方法}//新增业务方法public void addedBehavior() {……}
}

注意:由于在抽象装饰类Decorator中注入的是Component类型的对象,因此可以将一个具体构件对象注入其中,再通过具体装饰类来进行装饰;此外,还可以将一个已经装饰过的Decorator子类的对象再注入其中进行多次装饰,从而对原有功能进行多次扩展。

2)案例-完整解决方案
1.结构图

在这里插入图片描述

Component充当抽象构件类,其子类Window、TextBox、ListBox充当具体构件类,Component类的另一个子类ComponentDecorator充当抽象装饰类,ComponentDecorator的子类ScrollBarDecorator和BlackBorderDecorator充当具体装饰类。

2.代码案例

抽象构件类

//抽象构件类
abstract class Component {public abstract void display();
}

具体构件类

//具体构件类
public class Window extends Component {public void display() {System.out.println("显示窗体!");}
}//具体构件类
public class TextBox extends Component {public void display() {System.out.println("显示文本框!");}
}

抽象装饰类

//抽象装饰类
public class ComponentDecorator extends Component {//维持对抽象构件类型对象的引用private Component component;//注入抽象构件类型的对象public ComponentDecorator(Component component){this.component = component;}public void display() {component.display();}
}

具体装饰类

//黑色边框装饰类:具体装饰类
public class BlackBorderDecorator extends ComponentDecorator {public BlackBorderDecorator(Component component) {super(component);}public void display() {this.setBlackBorder();super.display();}public void setBlackBorder() {System.out.println("为构件增加黑色边框!");}
}

客户端类

public class Client{public  static void main(String[] args) {//使用抽象构件定义Component component,componentBB;//定义具体构件component = new Window();//定义装饰后的构件componentBB = new BlackBorderDecorator(component);componentBB.display();}
}
3)透明装饰模式与半透明装饰模式
1.透明装饰模式

a) 定义

在透明装饰模式中,要求客户端完全针对抽象编程。

客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型。

b) 代码案例

//使用抽象构件类型定义对象
Component  c, c1; c = new ConcreteComponent();
c1 = new ConcreteDecorator (c);

c) 注意

透明装饰模式可以让客户端透明地使用装饰之前的对象和装饰之后的对象,无须关心它们的区别。

可以对一个已装饰过的对象进行多次装饰,得到更为复杂、功能更为强大的对象。

在实现透明装饰模式时,要求具体装饰类的operation()方法覆盖抽象装饰类的operation()方法,除了调用原有对象的operation()外还需要调用新增的addedBehavior()方法来增加新行为。

2.半透明装饰模式

a) 定义

用具体装饰类型来定义装饰之后的对象,而具体构件类型还可以使用抽象构件类型来定义。

对客户端而言,具体构件类型无须关心,是透明的;但是具体装饰类型必须指定,这是不透明的。

b) 代码案例

……
//使用抽象构件类型定义
Document  doc; 
doc = new PurchaseRequest();//使用具体装饰类型定义
Approver newDoc; 
newDoc = new Approver(doc);
……

c) 注意

半透明装饰模式可以给系统带来更多的灵活性,设计相对简单,使用起来也非常方便。

不能实现对同一个对象的多次装饰,而且客户端需要有区别地对待装饰之前的对象和装饰之后的对象。

4)总结
1.优点
  • 对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加。

  • 可以通过动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为。

  • 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出不同行为的组合,得到功能更为强大的对象。

  • 具体构件类与具体装饰类可以独立变化,可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合“开闭原则”。

2.缺点
  • 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,大量小对象的产生势必会占用更多的系统资源,在一定程序上影响程序的性能。

  • 装饰模式提供了一种比继承更加灵活机动的解决方案,但也意味着比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。

3.适用场景
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

  • 当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式。

不能采用继承的情况

第一类是系统中存在大量独立的扩展,为支持每一种扩展或者扩展之间的组合将产生大量的子类,使得子类数目呈爆炸性增长;

第二类是因为类已定义为不能被继承(如Java语言中的final类)。

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

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

相关文章

HBase的Python API操作(happybase)

一、Windows下安装Python库:happyhbase pip install happybase -i https://pypi.tuna.tsinghua.edu.cn/simple 二、 开启HBase的Thrift服务 想要使用Python API连接HBase,需要开启HBase的Thrift服务。所以,在Linux服务器上,执行…

uniapp 苹果支付内购示例代码

// #ifdef APPasync init() {uni.showLoading({title: 检测支付环境...});try {// 初始化,获取iap支付通道await this._iap.init();// 从苹果服务器获取产品列表this.productList await this._iap.getProduct();this.productList[0].checked true;this.productId …

NVIDIA 发布 Project GR00T 人形机器人基础模型和 Isaac 机器人平台重大更新

系列文章目录 前言 Isaac 机器人平台现可为开发者提供全新的机器人训练仿真器、Jetson Thor 机器人计算机、生成式 AI 基础模型和由 CUDA 加速的感知和操作库。 Project GR00T 是一种多模态人形机器人通用基础模型,作为机器人的大脑,使它们能够学习技能…

0DAY漏洞是什么,如何进行有效的防护

零日漏洞,指的是软件或系统中未被公开的、未被厂商知晓的安全漏洞。这些漏洞未被修复,因此黑客可以利用它们进行攻击,而受害者往往无法防范。由于这些漏洞的存在时间很短,因此称之为“零日漏洞”,也称为“0day漏洞”。…

R使用netmeta程序包实现二分类数据的频率学网状meta分析

该研究检索了Cochrane对照试验中心注册,CINAHL,Embase,LILACS数据库,MEDLINE,MEDLINEIn-Process,PsycINFO,监管机构网站,以及从一开始就发布和未发表的双盲随机对照试验的国际注册20…

集合系列(十五) -CopyOnWriteArrayList详解

一、摘要 在介绍 CopyOnWriteArrayList 之前&#xff0c;我们一起先来看看如下方法执行结果&#xff0c;代码内容如下&#xff1a; public static void main(String[] args) {List<String> list new ArrayList<String>();list.add("1");list.add(&quo…

Elasticsearch-相关性

相关性描述的是⼀个⽂档和查询语句匹配的程度。ES 会对每个匹配查询条件的结果进⾏算分_score。_score 的评分越高&#xff0c;相关度越高。 ES 5.0之前使用TF-IDF 相关性算法&#xff0c; 5.0之后使用了BM25算法 TF-IDF 公式 score(q,d) queryNorm(q) coord(q,d) …

将jupyter notebook文件导出为pdf(简单有效)

1.打开jupyter notebook笔记&#xff1a; 2.点击file->print Preview 3.在新打开的页面右键打印 4.另存为PDF 5.保存即可 6.pdf效果 &#xff08;可能有少部分图片显示不了&#xff09; 网上也有其他方法&#xff0c;比如将其转换为.tex再转为PDF等&#xff0c;但个人觉…

如何在 Mac/Windows 上从 iPhone 备份中恢复短信?

- “如何从 iPhone 备份中提取短信&#xff1f;” 短信正在取代日常生活和工作中的电话和电子邮件。 iPhone 上的短信现在是您与朋友、家人、亲人和同事最重要的沟通方式之一。有时&#xff0c;您可能想在 iPhone 上保留一些您不想丢失的特殊消息&#xff0c;也许这是朋友的一…

以太网链路聚合——增加带宽,解决生成树收敛慢的问题

目录 一.对STP生成树的补充 1.STP接口状态 2.STP生成树的改进 二.网络可靠性 1.单板可靠性 2.设备可靠性 3.链路可靠性 三.链路聚合 1.多条链路聚合增加带宽 2.链路聚合术语 四.链路聚合模式 1.手动模式 2.LASP模式 &#xff08;1).LASP术语 &#xff08;2&…

Pillow教程07:调整图片的亮度+对比度+色彩+锐度

---------------Pillow教程集合--------------- Python项目18&#xff1a;使用Pillow模块&#xff0c;随机生成4位数的图片验证码 Python教程93&#xff1a;初识Pillow模块&#xff08;创建Image对象查看属性图片的保存与缩放&#xff09; Pillow教程02&#xff1a;图片的裁…

快速幂算法在Java中的应用

引言&#xff1a; 在计算机科学和算法领域中&#xff0c;快速幂算法是一种用于高效计算幂运算的技术。在实际编程中&#xff0c;特别是在处理大数幂运算时&#xff0c;快速幂算法能够显著提高计算效率。本文将介绍如何在Java中实现快速幂算法&#xff0c;并给出一些示例代码和应…