一、概述

  动态地给一个对象添加一些额外的职责。就增加功能来说, Decorator模式相比生成子类更为灵活。该模式以对客 户端透明的方式扩展对象的功能。

  UML简图

  

  角色

  

  在持有Component的引用后,由于其自身也是Component的子类,那么,相当于ConcreteDecorator包裹了Component,不但有Component的特性,同时自身也可以有别的特性,也就是所谓的装饰

二、实践

  根据上面的角色,创建相应的角色

  抽象构件

/**
* 抽象组件
*
* @author Administrator
* 日期: 2017/10/28
**/
public interface Component {
void operation1();
}

  具体构件

/**
* 具体组件
*
* @author Administrator
* 日期: 2017/10/29
**/
public class ConcreteComponent implements Component{
@Override
public void operation1() {
// 具体操作
System.out.println("明星唱歌!");
}
}

  装饰者

/**
* 装饰者
*
* @author Administrator
* 日期: 2017/10/29
**/
public class Decorator implements Component{
private Component component; public Decorator(Component component) {
this.component = component;
} public Decorator() {
} @Override
public void operation1() {
// 调用component的操作方法
component.operation1();
}
}

  具体装饰者(可以有不同的装饰者)

/**
* 具体装饰者
*
* @author Administrator
* 日期: 2017/10/29
**/
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component c) {
super(c);
}
@Override
public void operation1() {
System.out.println("先交门票钱!");
super.operation1();
}
}

  装饰者2号

/**
* 具体装饰者2号
*
* @author Administrator
* 日期: 2017/10/29
**/
public class ConcreteDecorator2 extends Decorator{
public ConcreteDecorator2(Component c) {
super(c);
}
@Override
public void operation1() {
System.out.println("先点击购票!");
super.operation1();
}
}

  一个典型的装饰者模式的出场方式如下:(比如我们的缓冲流)

  

  客户端实际使用示例

/**
* 客户端
* @author Administrator
* 日期: 2017/10/26
**/
public class Client {
public static void main(String[] args) {
Component c = new ConcreteComponent();
Decorator d = new ConcreteDecorator(new ConcreteDecorator2(c));
d.operation1();
}
}

  // 这样使用是基于家谱的正确性(所以上图的参数可以正确传递),如下图所示:

  

  结果如下:

  

 过程分析:

  关键是每个具体装饰类都有一个super的构造的调用,首先看d.opreation1()方法,调用了装饰者1的方法,里面先执行了自己的逻辑,再执行c.opreation1()

但此时这个c这个Component是构造器里传入的装饰者2(家谱的正确性),关键就是实现了同一接口(看家谱图),所以最后出现了1和2叠加的逻辑。

  具体的装饰过程如果还不是很理解,可以 尝试着在IDE里看看代码的调用

三、改进与思考

  适用场景

  

  实际案例(Java IO)

  

  模式简化

   1. 如果没有Component接口,只有一个ConcreteComponent,那么Decorator是此ConcreteComponent(扮演双重角色)的一个子类

    2.如果只有一个ConcreteDecoretor类(甚至只有两个也可以这么做),那么可以没有Decorator接口,可以把Decoretor和ConcreteDecorator类合并为一个类

  一句口诀

  是你还有你,一切拜托你。(意会)

  透明性要求

  根据透明性要求,我们也可以利用多态很容易做到这点:(如果子类有新增的方法,则不能采用此方式),

 public static void main(String[] args) {
Component c = new ConcreteComponent();
Component d = new ConcreteDecorator(new ConcreteDecorator2(c));
d.operation1();
}

  装饰者和被装饰者拥有不完全一样的接口(例如装饰者有新增方法),则称为不完全透明的装饰者模式!

  

Java设计模式(9)——结构型模式之装饰模式(Decorator)的更多相关文章

  1. Java设计模式之结构型模式

    结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. 一.适配器模式: 意图: 将一个类的接口转换成客户希望的另外一个接口.Adapter 模式使得原本由于接 ...

  2. GoF23种设计模式之结构型模式之装饰模式

    一.概述 动态地给一个对象添加一些额外的职责.装饰模式比生成子类更为灵活. 二.适用性 1.在不影响其他对象的情况下,以动态.透明的方式给但个对象添加职责. 2.处理那些可以撤销的职责. 3.当不能采 ...

  3. Java经典23种设计模式之结构型模式(一)

    结构型模式包含7种:适配器模式.桥接模式.组合模式.装饰模式.外观模式.享元模式.代理模式. 本文主要介绍适配器模式和桥接模式. 一.适配器模式(Adapter) 适配器模式事实上非常easy.就像手 ...

  4. GoF的23种设计模式之结构型模式的特点和分类

    结构型模式描述如何将类或对象按某种布局组成更大的结构.它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象. 由于组合关系或聚合关系比继承关系耦合度低,满足 ...

  5. Go语言实现的23种设计模式之结构型模式

    摘要:本文主要聚焦在结构型模式(Structural Pattern)上,其主要思想是将多个对象组装成较大的结构,并同时保持结构的灵活和高效,从程序的结构上解决模块之间的耦合问题. 本文分享自华为云社 ...

  6. 结构型模式(三) 装饰模式(Decorator)

    一.动机(Motivate) 在房子装修的过程中,各种功能可以相互组合,来增加房子的功用.类似的,如果我们在软件系统中,要给某个类型或者对象增加功能,如果使用"继承"的方案来写代码 ...

  7. GoF23种设计模式之结构型模式之组合模式

    一.概述 将对象组合成树型结构以表示“部分--整体”的层次关系.组合模式使得用户对单个对象和组合对象的使用具有一致性. 二.适用性 1.你想表示对象的部分--整体层次结构的时候. 2.你希望用户忽略组 ...

  8. GoF23种设计模式之结构型模式之享元模式

    一.概述  运用共享技术有效地支持大量细粒度的对象. 二.适用性 1.当一个应用程序使用了大量的对象的时候. 2.由于使用大量的独享而造成很大的存储开销的时候. 3.对象的大多数状态都可变为外部状态的 ...

  9. 设计模式(7)-结构型模式-Bridge模式

    2.结构性模式 2.2  BRIDGE模式 别名:handle/body 这个模式体现了组合相对于继承的优势. 2.2.1动机 当一个抽象可能有多个实现时,通经常使用继承来协调它们.抽象类定义对该抽象 ...

随机推荐

  1. TCP、UDP、Socket 通信(原)

    说明:本随笔主要演示自己给自己发送消息例子,分别使用了TCP协议.UDP协议以及socket套接字通信.使用socket套接字了模拟TCP.UDP通信实现原理.其中有些源码都来自<C#高级编程 ...

  2. 容器,Docker, Kubernetes和Kyma,以及Kyma对SAP的意义

    大家好,今天非常高兴能给大家做一个关于Kyma的技术分享.这个session的audience主要是针对使用咱们成都研究院使用Java和nodejs等技术栈做微服务开发的同事们.对于在ABAP net ...

  3. jquery获取前一个月日期

    一) 重构Date对象: // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s).季度(q) 可以用 1-2 个占位符, // 年 ...

  4. Android(java)学习笔记207:Android下的属性动画(Property Animation)

    1. 属性动画(Property Animation)引入: 在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系统在一开始的时候就给我们提供了两种实现动画效果的方式,逐帧动画(fra ...

  5. checkbox的readonly属性设置

    方式一: checkbox没有readOnly属性,如果使用disabled=“disabled”属性的话,会让checkbox变成灰色的,用户很反感这种样式可以这样让它保持只读: 设置它的oncli ...

  6. Layer Trees Reflect Different Aspects of the Animation State

    https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/CoreA ...

  7. Yii自定义验证规则

    简单的方法:在 model 内部定义规则 最简单的定义验证规则的方法是在使用它的模型(model)内部定义. 比方说,你要检查用户的密码是否足够安全. 通常情况下你会使用 CRegularExpres ...

  8. newcoder NOIP提高组模拟赛C题——保护

    我是发了疯才来写这道题的 我如果用写这道题的时间去写dp,我估计我能写上三四道 可怕的数据结构题 题目 这道题的鬼畜之处在于实在是不太好写 我们看到要求离树根尽量的近,所以我们很容易就能想到树上倍增, ...

  9. Hive之数据类型

    Hive之数据类型   (本文是基于多篇文章根据个人理解进行的整合,参考的文章见末尾的整理) 数据类型 Hive支持两种数据类型,一类叫原子数据类型,一类叫复杂数据类型.原子数据类型包括数值型.布尔型 ...

  10. VC++和C语言中常见数据类型转换为字符串的方法

    1.短整型(int) itoa(i,temp,10);///将i转换为字符串放入temp中,最后一个数字表示十进制 itoa(i,temp,2); ///按二进制方式转换 2.长整型(long) lt ...