设计模式:装饰者模式

2023-11-07

定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。
设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。

要点: 装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为。

//定义公共接口
public interface Human {
	public void wearClothes();
 
	public void walkToWhere();
}

//定义被装饰者,被装饰者初始状态有些自己的装饰
public class Person implements Human {
 
	@Override
	public void wearClothes() {
		// TODO Auto-generated method stub
		System.out.println("穿什么呢。。");
	}
 
	@Override
	public void walkToWhere() {
		// TODO Auto-generated method stub
		System.out.println("去哪里呢。。");
	}
}
 
//定义装饰者
public abstract class Decorator implements Human {
	private Human human;
 
	public Decorator(Human human) {
		this.human = human;
	}
 
	public void wearClothes() {
		human.wearClothes();
	}
 
	public void walkToWhere() {
		human.walkToWhere();
	}
}
 
//下面接着定义三种装饰,这是第一个,第二个第三个功能依次细化,即装饰者的功能越来越多
public class Decorator_zero extends Decorator {
 
	public Decorator_zero(Human human) {
		super(human);
	}
 
	public void goHome() {
		System.out.println("进房子。。");
	}
 
	public void findMap() {
		System.out.println("书房找找Map。。");
	}
 
	@Override
	public void wearClothes() {
		// TODO Auto-generated method stub
		super.wearClothes();
		goHome();
	}
 
	@Override
	public void walkToWhere() {
		// TODO Auto-generated method stub
		super.walkToWhere();
		findMap();
	}
}
 
public class Decorator_first extends Decorator {
 
	public Decorator_first(Human human) {
		super(human);
	}
 
	public void goClothespress() {
		System.out.println("去衣柜找找看。。");
	}
 
	public void findPlaceOnMap() {
		System.out.println("在Map上找找。。");
	}
 
	@Override
	public void wearClothes() {
		// TODO Auto-generated method stub
		super.wearClothes();
		goClothespress();
	}
 
	@Override
	public void walkToWhere() {
		// TODO Auto-generated method stub
		super.walkToWhere();
		findPlaceOnMap();
	}
}
 
public class Decorator_two extends Decorator {
 
	public Decorator_two(Human human) {
		super(human);
	}
 
	public void findClothes() {
		System.out.println("找到一件D&G。。");
	}
 
	public void findTheTarget() {
		System.out.println("在Map上找到神秘花园和城堡。。");
	}
 
	@Override
	public void wearClothes() {
		// TODO Auto-generated method stub
		super.wearClothes();
		findClothes();
	}
 
	@Override
	public void walkToWhere() {
		// TODO Auto-generated method stub
		super.walkToWhere();
		findTheTarget();
	}
}
 
//测试类,看一下你就会发现,跟java的I/O操作有多么相似
public class Test {
	public static void main(String[] args) {
		Human person = new Person();
		Decorator decorator = new Decorator_two(new Decorator_first(
				new Decorator_zero(person)));
		decorator.wearClothes();
		decorator.walkToWhere();
	}
}

其实就是进房子找衣服,然后找地图这样一个过程,通过装饰者的三层装饰,把细节变得丰富。

关键点:

1、Decorator抽象类中,持有Human接口,方法全部委托给该接口调用,目的是交给该接口的实现类即子类进行调用。

2、Decorator抽象类的子类(具体装饰者),里面都有一个构造方法调用super(human),这一句就体现了抽象类依赖于子类实现即抽象依赖于实现的原则。因为构造里面参数都是Human接口,只要是该Human的实现类都可以传递进去,即表现出Decorator dt = new Decorator_second(new Decorator_first(new Decorator_zero(human)));这种结构的样子。

所以当调用dt.wearClothes();dt.walkToWhere()的时候,又因为每个具体装饰者类中,都先调用super.wearClothes和super.walkToWhere()方法,而该super已经由构造传递并指向了具体的某一个装饰者类(这个可以根据需要调换顺序),那么调用的即为装饰类的方法,然后才调用自身的装饰方法,即表现出一种装饰、链式的类似于过滤的行为。

3、具体被装饰者类,可以定义初始的状态或者初始的自己的装饰,后面的装饰行为都在此基础上一步一步进行点缀、装饰。
4、装饰者模式的设计原则为:对扩展开放、对修改关闭,这句话体现在我如果想扩展被装饰者类的行为,无须修改装饰者抽象类,只需继承装饰者抽象类,实现额外的一些装饰或者叫行为即可对被装饰者进行包装


装饰者模式和代理模式简单对比

这两个设计模式看起来很像。对装饰器模式来说,装饰者(decorator)和被装饰者(decoratee)都实现同一个 接口。对代理模式来说,代理类(proxy class)和真实处理的类(real class)都实现同一个接口。此外,不论我们使用哪一个模式,都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。

然而,实际上,在装饰器模式和代理模式之间还是有很多差别的。装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。

总结来说就是:

1.代理模式强调的是控制,装饰模式强调的是增强。

2.代理模式强调的是透明访问,装饰模式强调的是自由构建。

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

设计模式:装饰者模式 的相关文章

  • 怎样给手机发送短信验证码

    1 首先你得去短信平台申请账户 我之前用的是梦网云短信平台 这里也是讲用梦网云短信平台发送短信 2 网址 http www monyun cn account new activity html B vid 1400037279266705
  • systemctl和service

    一直以为这两个功能是一样的 某些情况下systemctl比service功能还要强 但是工作中遇到了问题 在这里 用service操作libvirt bin 但是无法用systemctl处理 查阅资料 service其实是在 etc ini
  • python django 优势_那么多人选择Python,它的优势,缺点有哪些?

    提及到目前最火的编程语言 Python可谓是非常受欢迎的 属于四大编程语言之一 近些年来Python的增长趋势也是非常明显的 很多人都将Python作为入门的语言 对于很多人来说都会选择学习Python 那么Python究竟有何魔力呢 它的
  • 使用vue+electron创建桌面软件(二)

    文章目录 打包配置 界面配置 窗口配置 自定义顶部栏 vue electron项目 对软件进行配置 包括打包图标 名称等 自定义窗口最小化 全屏 退出软件 界面信息传递等 打包配置 在vue config js文件中 vue config
  • 射击小游戏c语言实验报告,C++实现简单射击小游戏

    使用c 制作简单的横板射击小游戏 供大家参考 具体内容如下 include include include class Bullet class Tank class E Bullet class Boss bool dead false
  • k8s-某视频课基础了解

    容器编排 Kubernetes Helm 容器引擎 Containerd Rocket 容器镜像仓库 TUF Harbor Notarv 容器网络CNI 服务网格 服务发现 CoreDNS Linkerd Envoy 容器监控运维 Prom
  • [Ubuntu]使用随机数完全格式化整块优盘

    系统对优盘等存储设备的快速格式化 只是做了简单的标记 如果没有进一步的写入操作 内容大概率都还能恢复找回 那个如何彻底的格式化掉一块优盘呢 使用 Ubuntu 我们可以对全盘进行写零或者写随机数操作 1 找到 U 盘路径 sudo fdis
  • 运维进阶:文件共享服务全攻略

    一 了解一下 1 NFS NFS Network File System 即网络文件系统 是FreeBSD支持的文件系统中的一种 它允许网络中的计算机之间通过TCP IP网络共享资源 在NFS的应用中 本地NFS的客户端应用可以透明地读写位
  • np.maximum()的用法

    一 用法 np maximum A B 用于逐元素比较两个array的大小 二 实例 import numpy as np A np array 1 2 3 4 B np array 5 6 7 8 print np maximum A B
  • WPF随笔(十)--使用AvalonDock实现可停靠式布局

    我们每天使用的许多软件都使用了可停靠式布局 可以方便的打开 关闭 收起 展开 移动选项卡 今天就来说明如何使用AvalonDock实现这种可停靠式布局 AvalonDock安装 最新版本的AvalonDock类库包含在程序包Extended

随机推荐

  • Python packaging tools not found的问题解决

    首先 我用的虚拟机装的linux系统 linux自带的python2 7 所以python的安装工具是python2的 当使用python3 6 也就是在在项目中设置python3 6的时候 系统自动调用的是python2的下载工具 所以就
  • mycat学习01之认识mycat

    转载自 Mycat V1 6 0权威指南 pdf 一书
  • 射雕英雄传ol显示服务器断开,射雕英雄传OL5月28日维护更新内容

    为带来更好的游戏体验 射雕英雄传OL 全体服务器将于5月28日上午9 00 12 00期间进行例行停机维护与版本升级 今天小编就给大家带来 射雕英雄传OL 5月28日维护更新内容 此次版本升级详细内容如下 一 新增装备部位 翅膀 1 玩家升
  • 在线瓦片地图服务资源 总结

    常见的公开在线瓦片地图服务汇总 https www cnblogs com amadoGrowers p 13631127 html
  • Android O中修改NotificationChannel 属性,升级app后该修改不生效,必须卸载app重新安装才能生效

    Android 8 0中修改NotificationChannel 属性 升级app后该修改不生效 必须卸载app重新安装才能生效 原代码如下 public void notifyDownloading long progress long
  • 基于centos7的Openssh版本升级

    一 环境准备 yum y install wget tar gcc make 二 上传升级的软件包 zlib 1 2 11 tar gz openssl 1 1 1d tar gz openssh 9 0p1 tar gz 下载地址 zli
  • angular4-X知识点汇总

    1 生成新项目 ng new my app 生成过程会有点长 主要是需要下载很多的包 2 启动开发服务器 npm run start ng serve open ng serve o 3 NgModule是一个装饰器函数 它接收一个用来描述
  • 数星星(树状数组的理解与应用)

    数星星问题 文章目录 数星星问题 前导 问题详情 问题分析 关键语句分析 方法判断 代码 总结 前导 树状数组的原理详见如下链接 链接 https blog csdn net 2302 77698668 article details 13
  • Leptonica PIX 与 Qt QImage 的相互转换

    最近有个项目需要用到 OCR 功能 研究了一下 感觉 Tesseract 还不错 准备在项目中试试 但是发现 Tesseract 底层图像数据用到了 Leptonica 而我的程序准备用 Qt C 来写 这里就涉及一个问题 如何把 QIma
  • 提示Cannot resolve symbol xxx的解决办法

    今天有读者反映在spring boot项目中 已经导入了所有需要的包 但是提示如下错误 Cannot resolve symbol xxx 该错误的解决办法是 1 单击IDEA开发工具的File gt Invalidate Caches R
  • 数据结构视频教程 -《(东南大学 王茜)数据结构 (64讲)》

    整个视频打包下载地址 史上最全的数据结构视频教程系列分享之 东南大学 王茜 数据结构 64讲 转载请保留出处和链接 更多优秀资源请访问 我是码农 数据结构对于从事计算机系统软件和应用软件设计与开发人员非常重要 程序设计语言为数据结构的描述提
  • 基于Spring Boot开发的社区物业管理系统

    文章目录 项目介绍 主要功能截图 登录 车位收费管理 物业收费管理 投诉信息管理 车位管理 保修统计分析 部分代码展示 设计总结 项目获取方式 作者主页 Java韩立 简介 Java领域优质创作者 简历模板 学习资料 面试题库 关注我 都给
  • 【python教程入门学习】学习Python爬虫前的准备工作

    在使用 Python 编写爬虫程序之前 您需要提前做一些准备工作 这样在后续学习过程中才会得心应手 知识准备 1 Python语言 Python 爬虫作为 Python 编程的进阶知识 要求学习者具备较好的 Python 编程基础 对于没有
  • 浏览器输入url后发生了什么?

    在浏览器输入url后会发生的过程 1 DNS对域名进行解析 2 建立TCP连接 三次握手 3 发送HTTP请求 4 服务器处理请求 5 返回响应结果 6 关闭TCP连接 四次挥手 7 浏览器解析HTML 8 浏览器布局渲染 1 浏览器对输入
  • Flink流和表的转换

    流 表的转换 1 这种方式后续要进行tableSql的操作 推荐 tableEnv createTemporaryView tableName dataStream 2 这种方式后续要进行tableApi的操作不常用 Table table
  • Linux文件权限管理 chmod 读、写、可执行

    使用 ls l 查看文件权限 左侧第一列 rw r r 这些就是文件的权限信息 文件的权限分为三种 三种权限可相互叠加 最高权限为7 权限 字母 对应的二进制 对应的八进制 读 r 100 4 写 w 010 2 可执行 x 001 1 嗯
  • ajax传参数json对象到后台获取

    var data data name pxxx paramData dataSource a1 table t1 field f1 r name1 01 p name2 02 p 10 100 name2 01 p dataSource a
  • 输入若干个整数,当输入0时表示结束,统计每个输入整数的出现次数。

    描述 输入若干个整数 当输入0时表示结束 统计每个输入整数的出现次数 输入 输入若干个整数 整数之间以空格间隔 当输入0时表示结束 输出 分行输出每个整数出现的次数 行末不能有多余空格 输入示例 11 22 35 68 97 63 22 6
  • 内存分页、进程分页、页表长度

    内存分页 进程分页 页表长度 内存分页 内存空间分成一个个大小相等的分区 页框号或物理块号从0开始 每一个分区称作页框 一般大小为 4KB 进程分页 将用户进程的地址空间分为与页框大小相等的一个个区域 页号一般从0开始 每一个分区称作页 一
  • 设计模式:装饰者模式

    定义 动态给一个对象添加一些额外的职责 就象在墙上刷油漆 使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活 设计初衷 通常可以使用继承来实现功能的拓展 如果这些需要拓展的功能的种类很繁多 那么势必生成很多子类 增加系统