JAVA设计模式(21) —装饰(Decorator)模式

2023-10-31

定义:动态的给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。

类型:对象结构型模式

别名:包装模式(Wrapper)

类图:



Decorator装饰模式是一种结构型模式,它主要是解决:“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀(多继承)。继承为类型引入的静态特质的意思是说以继承的方式使某一类型要获得功能是在编译时。所谓静态,是指在编译时;动态,是指在运行时。


装饰设计模式的结构

  • Component:定义一个对象接口,可以给这些对象动态的添加职责。
  • ConcreteComponent:定义一个对象可以给这个对象动态的添加职责。
  • Decorator:维护一个指向Component对象的指针,并定义一个与Component接口一致的接口,或者直接实现Component对象。

协作关系:Decorator把来自客户端的请求发送给所装饰的ConcreteComponent,在发送请求的前后执行一些附加的动作。


实现代码

用Decorator模式实现一下对某个手机的GSP和蓝牙功能扩展

首先,定义一个手机的接口或者是抽象类,这里就用抽象类来实现,代码如下:

//抽象接口 --> Component
abstract class AbstractCellPhone{
	public abstract String callNumber();
    public abstract String sendMessage();
}


然后,再来实现Android和IPhone的手机类,这类要继承CellPhone,也就是图中ConcreteComponent类要继承Component,实现代码如下:

// Android厂商的手机 -->ConcreteComponent
class AndroidCellPhone extends AbstractCellPhone{

	@Override
	public String callNumber() {
		
		return "callNumber from Android terminal";
	}

	@Override
	public String sendMessage() {
		
		return "sendMessage from Android terminal";
	}
	
}
class IPhoneCellPhone extends AbstractCellPhone{

	@Override
	public String callNumber() {
		
		return "callNumber from IPhone terminal";
	}

	@Override
	public String sendMessage() {
		
		return "sendMessage from IPhone terminal";
	}
}

接下来需要定义一个接口或者抽象类 Decorator,实现代码如下:
//抽象接口 --> Decorator
abstract class Decorator extends AbstractCellPhone{
	protected AbstractCellPhone mCellPhone;
	public Decorator(AbstractCellPhone mCellPhone) {
		this.mCellPhone = mCellPhone;
	}
	@Override
	public String callNumber() {
		return mCellPhone.callNumber();
	}
	@Override
	public String sendMessage() {
		return mCellPhone.sendMessage();
	}
}

Decorator既继承了AbstractCellPhone,又包含了一个私有的AbstractCellPhone的对象。这样做的意义是:Decorator类又使用了另外一个Component类。我们可以使用一个或多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。

紧接着,实现GSP和蓝牙的功能扩展,它们继承自Decorator,代码如下:

//具体装饰类 GPS功能扩展  --> ConcreteDecorator
class DecoratorGPS extends Decorator{

	public DecoratorGPS(AbstractCellPhone mCellPhone) {
		super(mCellPhone);
	}

	@Override
	public String callNumber() {
		return super.callNumber() +" GPS";
	}

	@Override
	public String sendMessage() {
		return super.sendMessage() +" GPS";
	}
}
class DecoratorBlueTooth  extends Decorator{

	public DecoratorBlueTooth (AbstractCellPhone mCellPhone) {
		super(mCellPhone);
	}

	@Override
	public String callNumber() {
		return super.callNumber() +" BlueTooth";
	}

	@Override
	public String sendMessage() {
		return super.sendMessage() +" BlueTooth";
	}
}

最后,客户调用代码

//客户 Client
public class DecoratorClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		AbstractCellPhone mCellPhone = new AndroidCellPhone();
		
		System.out.println(mCellPhone.callNumber() +"\n" +mCellPhone.sendMessage());
		
		System.out.println("-------------------------------------------");
		
		Decorator gps = new DecoratorGPS(mCellPhone);
		
		System.out.println(gps.callNumber() +"\n" +gps.sendMessage());
		
		System.out.println("-------------------------------------------");
		
		Decorator bluetooth = new DecoratorBlueTooth(mCellPhone);
		
		System.out.println(bluetooth.callNumber() +"\n" +bluetooth.sendMessage());
		
	}
}


Decorator模式的优缺点

  1. 比静态继承更灵活 与对象的静态继承相比,Decorator模式提供了更加灵活的向对象添加职责的方式,可以使用添加和分离的方法,用装饰在运行时刻增加和删除职责。使用继承机制增加职责需要创建一个新的子类,如果需要为原来所有的子类都添加功能的话,每个子类都需要重写,增加系统的复杂度,此外可以为一个特定的Component类提供多个Decorator,这种混合匹配是适用继承很难做到的。
  2. 避免在层次结构高层的类有太多的特征,Decorator模式提供了一种“即用即付”的方法来添加职责,他并不试图在一个复杂的可订制的类中支持所有可预见的特征,相反可以定义一个简单的类,并且用Decorator类给他逐渐的添加功能,可以从简单的部件组合出复杂的功能。
  3. Decorator 与它的Component不一样 Decorator是一个透明的包装,如果我们从对象标识的观点出发,一个被装饰了的组件与这个组件是有差别的,因此使用装饰时不应该以来对象标识。
  4. 产生许多小对象,采用Decorator模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅在他们相互连接的方式上有所不同。


适用场景

  1. 在不影响其他对象的情况下,以动态透明的方式给单个对象添加职责
  2. 处理那些可以撤销的职责。
  3.  当不能采用生成子类的方法进行扩充时,一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类的树木呈爆炸性增长,另一种可能是因为定义被隐蔽或类定义不能用于生成子类。


最后,自己有一点点费解,Decorator完全可以不用继承自Component类 实现相同的功能,但是最终还是继承自 Component,不大明白


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA设计模式(21) —装饰(Decorator)模式 的相关文章

  • java设计模式——原型模式(Prototype Pattern)

    概述 在使用原型模式时 我们需要首先创建一个原型对象 再通过复制这个原型对象来创建更多同类型的对象 需要注意的是通过克隆方法所创建的对象是全新的对象 它们在内存中拥有新的地址 通常对克隆所产生的对象进行修改对原型对象不会造成任何影响 每一个
  • Gof23设计模式之简单工厂/静态工厂模式

    在java中 万物皆对象 这些对象都需要创建 如果创建的时候直接new该对象 就会对该对象耦合严重 假如我们要更换对象 所有new对象的地方都需要修改一遍 这显然违背了软件设计的开闭原则 如果我们使用工厂来生产对象 我们就只和工厂打交道就可
  • Java设计模式-接口隔离原则

    接口隔离原则 Interface Segregation Principle 定义1 客户端不应该依赖它不需要的接口 一个类对另一个类的依赖应该建立在最小的接口上 Clients should not be forced to depend
  • Java创建型模式之原型模式

    原型模式 所谓原型模式 就是以一个对象为原型 返回这个对象的克隆 而不是创建一个新的对象 原型对象的优点 在Java中创建一个新对是昂贵和资源密集型 原型对象有助于创建更好性能的重复对象 原型模式的核心就是克隆 克隆又分为浅克隆 深克隆 1
  • 设计模式---适配器模式

    适配器模式 基本介绍 适配器模式 Adapter Pattern 将某个类的接口转换成客户端期望的另一个接口表示 主的目的是兼容性 让原本因接口不匹配不能一起工作的两个类可以协同工作 其别名为包装器 Wrapper 适配器模式属于结构型模式
  • 1.单例模式之饿汉式

    单例模式总结 特点 构造方法私有 提供一个全局访问点 实现方式 有很多 分四篇分别总结1 饿汉式 2 懒汉式 3 注册式 4 ThreadLocal 优点 内存中只有一个实例 减少内存开销 避免对资源多重占用 设置全局访问点 严格控制访问
  • 开放-封闭原则

    一 定义 开放 封闭原则 是说软件实体 类 模块 函数等等 应该是可扩展的 但是不可修改 ASD 这个原则其实是有两个特征 一个是说 对于扩展是开放的 Open for extension 对于更改是封闭的 Closed for modif
  • 浅析Java单例设计模式,自写demo,简单易懂

    单例模式特点 1 构造器私有 2 在一个Java应用程序中 可保证只有一个实例对象 3 只提供一个供外界调用的getInstance 方法 单例模式优点 1 减少某些对象的频繁创建 降低系统开销和内存占用 2 外部调用不使用new关键字 降
  • 设计模式(十五)中介者模式

    版权声明 转载必须注明本文转自晓 晨的博客 http blog csdn net niunai112 目录 目录 导航 前言 例子 总结 优点 缺点 Git地址 导航 设计模式之六大设计原则 设计模式 一 单例模式 设计模式 二 工厂模式
  • Java开发中的23种设计模式详解

    设计模式 Design Patterns 可复用面向对象软件的基础 设计模式 Design pattern 是一套被反复使用 多数人知晓的 经过分类编目的 代码设计经验的总结 使用设计模式是为了可重用代码 让代码更容易被他人理解 保证代码可
  • 设计模式之Adapter模式

    今天这篇文章 我们来讲将设计模式中的 Adapter模式 中文就是 适配器模式 先说说一个生活中适配器模式的案例 有助于理解 现在有一个100伏特的交流电源 我现在想给笔记本充电 但是笔记本只能用12伏特的直流电 那我们是不是不能用这个电源
  • 16、门面模式

    文章目录 package com example demo designpattern 门面模式 外观模式 结构型模式 隐藏系统的复杂性 并向客户端提供了一个客户端可以访问系统的接口 它向现有的系统添加一个接口 来隐藏系统的复杂性 门面模式
  • Head First Design Mode(15)-必以此终(模式分类及其他的设计模式)

    这即将是我所整理的设计模式的最终章 看看时间竟然已经过去了3个月了 时光太匆匆 主要内容 这里我会把我们已经学习到的设计模式进行归类划分 便于记忆 此外还会介绍下 原书中未提及的部分设计模式 做简单介绍 我们已经介绍过的设计模式 策略模式
  • 软件设计模式----访问者模式

    访问者模式 模式动机 对于系统中的某些对象 它们存储在同一个集合中 且具有不同的类型 而且对于该集合中的对象 可以接受一类称为访问者的对象来访问 而且不同的访问者其访问方式有所不同 访问者模式为解决这类问题而诞生 在实际使用时 对同一集合对
  • 12、适配器

    文章目录 package com example demo designpattern 又叫包装模式 Wrapper 各种 wrapper bridge 就是适配器模式 jbdc odbc bridge io 字节流字符流转换 角色 tar
  • Head First Design Mode(5)-工厂模式

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 工厂模式 烘烤OO的精华 烘烤某些松耦合的OO设计 除了使用new操作符之外 还有更多制造对象的方法 本章我们将了解到实例化的这个活动不应该总是公开的进行 认识到初始
  • 设计模式-责任链模式(Java)

    设计模式 责任链模式 在极客学院的视频中学习了一种设计模式的方式 责任链模式 在博客园中发现了这篇文章 讲的很详细 就把它的一些内容转载过来了 本文中 我们将介绍设计模式中的行为型模式职责链模式 职责链模式的结果看上去很简单 但是也很复杂
  • Gof23设计模式之工厂方法模式和抽象工厂模式

    在java中 万物皆对象 这些对象都需要创建 如果创建的时候直接new该对象 就会对该对象耦合严重 假如我们要更换对象 所有new对象的地方都需要修改一遍 这显然违背了软件设计的开闭原则 如果我们使用工厂来生产对象 我们就只和工厂打交道就可
  • Java设计模式-单例模式

    单例模式 在有些系统中 为了节省内存资源 保证数据内容的一致性 对某些类要求只能创建一个实例 这就是所谓的单例模式 单例模式的定义与特点 单例 Singleton 模式的定义 指一个类只有一个实例 且该类能自行创建这个实例的一种模式 例如
  • Java设计模式(1):观察者模式

    面向对象思想设计原则 在实际的开发中 我们要想更深入的了解面向对象思想 就必须熟悉前人总结过的面向对象的思想的设计原则 1 单一职责原则 其实就是开发人员经常说的 高内聚 低耦合 也就是说 每个类应该只有一个职责 对外只能提供一种功能 而引

随机推荐

  • Oracle删除重复数据只保留一条

    问题描述 merge数据时 找不到唯一的源数据 需要先删除有重复的数据 只保留一条 解决方式 查找表中多余的重复记录 多个字段 select from tmp a where a 料号 a 分类码 in select 料号 分类码 from
  • FFmpeg安装与使用+Java API/SpringBoot项目使用

    目录 下载安装 介绍与简单使用 在项目中的使用 配置文件 工具类 使用 下载安装 Download FFmpeg 解压到指定文件夹 介绍与简单使用 FFmpeg是一个开源的跨平台视频和音频处理工具 可以处理各种格式的音视频文件 FFmpeg
  • echarts实现人物树形关系图实例

    写这个栗子的时候主要因为是刚刚做一个项目 要用到人物关系图 所以一直在找合适插件 最后选择echarts2 0的tree图最合适这个关系图了 哈哈 话不多少 现在就把效果图献上吧 ps 照片是网上下载的 莫要见外啊 这个使用的是echart
  • 引入并使用Element

    引入并使用Element 开发工具与关键技术 MVC 作者 汤池 撰写时间 2022 4 7 1 首先需要打开DW软件 新建一个html网页 然后保存到一个文件夹当中 2 然后打开element官网 下载使用Element必须引用的脚本文件
  • 2022/1/22记录网页

    65条消息 102 bert词向量进行文本分类和命名实体识别 u012416045的博客 CSDN博客 bert文本识别https blog csdn net u012416045 article details 88373965 Bert
  • 记一次kafka无法生产发送消息排查经历

    参考 欢迎点击原文 https stackoverflow com questions 37902167 kafka error while fetching metadata with correlation id leader not
  • c语言中简单变量必须,C语言规定,简单变量做实参时,它和对应形参之间的数据传递方式是()。 (A)地址传递 (B)单向值传递 (C)由...

    参考答案如下 语言规应形C由一般来说 各种调查报告在结构上都可分成哪几个部分 定地址B单演示PPT的结尾部分一般建议展示以下内容 通过startService再次启动Service时 简单间不会再执行onCreate 函数 变量蛋白质分子的
  • 图机器学习课程笔记7

    维生素C吃多了会上火 个人CSDN博文目录 cs224w 图机器学习 2021冬季课程学习笔记集合 目录 思维大纲 中文笔记 思维大纲 中文笔记
  • 树莓派入门教程 - 0 - 准备篇 - 0.3 树莓派串口访问终端

    电脑需要提前安装的工具 SSH 串口 终端神器 MobaXterm 官网下载链接 https mobaxterm mobatek net download html 使用到的硬件 USB转TTL模块 CH340 和 CP2102均可 CP2
  • 1.2-知识图谱有什么用?

    知识图谱经过几年的发展已经得到广泛的应用 当知识图谱遇上人工智能 更加突显出了它的优势和价值 最先应用于搜索 最典型的就是在谷歌搜索引擎里面应用 谷歌是在2012年率先提出来知识图谱的概念 提出这个概念的最主要的目的就是用于改善它的搜索引擎
  • ospf小结

    ospf卡住的原因 route id相同 认证不通过 区域ID不同 特殊区域标示不一致 优先级都为0 无法选举 MTU值不匹配 包的交互不完整 网络中丢包等 LSA加载不完全 hello包时间不一致 MA网络掩码不一致 虚链路建邻ABR的两
  • JVM常量池最全详解-常量池/运行时常量池/字符串常量池/基本类型常量池,看这一篇就够了

    JVM常量池最全详解 常量池 运行时常量池 字符串常量池 基本类型常量池 看这一篇就够了 常量池详解 1 字面量和符号引用 1 1 字面量 1 2 符号引用 2 常量池vs运行时常量池 3 常量池 静态常量池 4 运行时常量池 5 字符串常
  • Introduction to Scientific Programing and Simulation Using R chapter 04 答案

    strong span style font size 32px Ex1 span strong span style color 33cc00 programe cha4 6 ex1 img src https img blog csdn
  • h-a-p-p-e-n-before原则的理解

    happen before 可真是一个经典又老生常谈的话题 规则一共就八条 但看起来总有种抓不住重点的感觉 今天再整理一下对这八条规则的理解 首先我的理解是 happen before 的语义与在什么什么之前发生完全没有关系 其语义是如果
  • 网络安全实验室 综合关 解析

    网站地址 http hackinglab cn ShowQues php type pentest 第一关 渗透测试第一期 先看看 登录界面 发现可以注册和忘记密码 忘记密码可以重置密码 思路如下 重置admin密码 发现 不能直接重置密码
  • 【赠书活动|第四期《互联网广告系统:架构、算法与智能化》】

    文章目录 内容简介 作者简介 读者对象 大咖推荐 抽奖方式 本期中奖者 广告平台的建设和完善是一项长期工程 例如 谷歌早于2003年通过收购Applied Semantics开展Google AdSense 项目 而直到20年后的今天 谷歌
  • sql连接查询

    sql连接查询 单表查询 student表 select 列名 from 表名 查看全表 SELECT FROM student 可以匹配为全选 在student表中查找赵六的信息 SELECT FROM student WHERE sna
  • 插入时出现MyBatisSystemException: nested exception is

    检查完xml文件没错后 还是出现错误 org mybatis spring MyBatisSystemException nested exception is org apache ibatis binding BindingExcept
  • SourceInsight4.0黑色背景主题

    SourceInsight4 0黑色背景主题 在网上找了一通花了好多积分最后发现只改了代码区 左右代码索引文件列表和函数调用关系图都还是白底 最后自己在设置里面找了找 发现在这个版本中SI已经内置了一些常用的主题配色 先放效果图 设置在这里
  • JAVA设计模式(21) —装饰(Decorator)模式

    定义 动态的给一个对象添加一些额外的职责 就增加功能来说 Decorator模式相比生成子类更为灵活 类型 对象结构型模式 别名 包装模式 Wrapper 类图 Decorator装饰模式是一种结构型模式 它主要是解决 过度地使用了继承来扩