一、定义

装饰模式的设计理念主要是以对客户端透明的方式动态扩展对象的功能,是继承关系的一个替代(继承会产生大量的子类,而且代码有冗余)。装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展。装饰模式把客户端的调用委派到被装饰类。装饰模式的关键在于这种扩展完全是透明的(装饰模式的透明性要求客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型),装饰模式的应用在java的I/O流中最为显著。

二、角色

  • 抽象构件角色(Component):通常是一个抽象类或者一个接口,定义了一系列方法,方法的实现可以由子类实现或者自己实现。通常不会直接使用该类,而是通过继承该类或者实现该接口来实现特定的功能。(例如,对于动物类,有一个抽象方法输出所有的功能,基本功能包括:呼吸,觅食,睡觉等等)
  • 具体构件角色(Concrete Component):是Component的子类,实现了对应的方法,它就是那个被装饰的类。(具体构建角色可以建立很多个,例如狗,猫,鸟等等,如果是狗,我们可以装饰一些吼叫的功能,吃肉的功能;鸟可以装饰一些飞行的功能,带有翅膀的功能等等。当然这些需要在具体装饰角色中去具体定义)
  • 装饰角色(Decorator):是Component的子类,它是具体装饰角色共同实现的抽象类(也可以是接口),并且持有一个Component类型的对象引用,它的主要作用就是把客户端的调用委派到被装饰类。
  • 具体装饰角色(Concrete Decorator):它是具体的装饰类,是Decorator的子类,当然也是Component的子类。它主要就是定义具体的装饰功能,例如上面说的,对于鸟这个具体构建角色而言,除了具备抽象构件角色基本的功能,它还具有一些飞行的功能,带翅膀的功能。那么我们可以把这两个功能定义成一个具体装饰角色1,对于狗这个具体构件角色而言,我们可以把吼叫,吃肉这两个功能定义成一个具体装饰角色2,这样,如果我们再定义一个狼这样的具体构件角色的时候,就可以直接用具体装饰角色2来进行装饰。

图片来源于(https://blog.csdn.net/nugongahou110/article/details/50413668)

三、Example

以上面所说的动物的例子来写代码演示。

抽象构件角色(对应动物类)

public interface Component {
void function();
}

具体构件角色(对应狗)

public class ConcreteComponent implements Component {

	@Override
public void function() {
System.out.println("基本功能:呼吸+觅食+睡觉");
} }

装饰角色

public class Decorator implements Component {

	private Component component; //持有一个Component类型的对象引用

	public Decorator(Component component) {
this.component = component;
} @Override
public void function() {
component.function(); //客户端的调用委派给具体的子类
} }

具体装饰角色(对应吼叫和吃肉这两个功能)

public class ConcreteDecorator extends Decorator {

	public ConcreteDecorator(Component component) {
super(component);
} @Override
public void function() {
super.function();
System.out.println("附加功能:");
this.eat();
this.bellow(); } private void eat() {
System.out.println("吃肉");
} private void bellow() {
System.out.println("吼叫");
}
}

客户端测试:

public class ClientTest {
public static void main(String[] args) {
Component component = new ConcreteComponent();
System.out.println("------装饰前:-------");
component.function();
Component newComponent = new ConcreteDecorator(component);
System.out.println("------装饰后:-------");
newComponent.function();
}
} 输出:
------装饰前:-------
基本功能:呼吸+觅食+睡觉
------装饰后:-------
基本功能:呼吸+觅食+睡觉
附加功能:吃肉+吼叫

四、应用

装饰者模式主要应用在Java的I/O流中,如果读者对I/O流体系比较混乱的话,不妨利用装饰者模式去理理思路。OutputStream和InputStream就对应于抽象构件角色(Component),FileInputStream和FileOutputStream就对应具体构件角色(ConcreteComponent),FilterOutputStream和FilterInputStream就对应着装饰角色(Decorator),而BufferedOutputStream,DataOutputStream等等就对应着具体装饰角色。

Java装饰者模式(Decorator)的更多相关文章

  1. 设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 用法

    装饰者模式(Decorator Pattern) Java的IO类 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716 ...

  2. 装饰器模式-Decorator(Java实现)

    装饰器模式-Decorator(Java实现) 装饰器模式允许向一个现有的对象添加新的功能, 同时又不改变其结构. 其中 "现有对象"在本文中是StringDisplay类. 添加 ...

  3. 浅谈设计模式--装饰者模式(Decorator Pattern)

    挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...

  4. java装饰者模式理解

    java 装饰者模式其实就是扩展子类的功能,和继承是一个性质. 但继承是在编译时就固定扩展了父类的一些功能,而装饰者模式是在运行过程中动态绑定对象,实现一个子类可以随时扩展功能. 将方法排列组合,也可 ...

  5. 【PHP设计模式 09_ZhuangShiQi.php】装饰器模式 (decorator)

    <?php /** * [装饰器模式 (decorator)] * 有时候发布一篇文章需要经过很多人手,层层处理 */ header("Content-type: text/html; ...

  6. 设计模式(八)装饰器模式Decorator(结构型)

    设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法 ...

  7. 设计模式 - 装饰者模式(Decorator Pattern) 具体解释

    装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者 ...

  8. 装饰者模式 Decorator

    项目:咖啡计费系统 背景:现有系统中有一个抽象类Beverage,有2个抽象方法GetDescription和Cost. namespace DecoratorPattern { /// <su ...

  9. 设计模式学习--装饰者模式(Decorator Pattern)

    概念: 装饰者模式(Decorator Pattern): 动态地将功能添加到对象,相比生成子类更灵活,更富有弹性. 解决方案: 装饰者模式的重点是对象的类型,装饰者对象必须有着相同的接口,也也就是有 ...

随机推荐

  1. MapReduce项目之气温统计

    在本博文,我们要学习一个挖掘气象数据的程序.气象数据是通过分布在美国全国各地区的很多气象传感器每隔一小时进行收集,这些数据是半结构化数据且是按照记录方式存储的,因此非常适合使用 MapReduce 程 ...

  2. springboot在lunix后台启动,退出账号也不关闭

    首先需要进到自己springboot项目的根目录,然后执行如下linux命令 nohup java -jar 自己的springboot项目.jar >日志文件名.log 2>&1 ...

  3. ABAP跳转屏幕

    1.call transaction语句跳转屏幕 '. CALL TRANSACTION 'VA03' AND SKIP FIRST SCREEN. . 2.调用函数 CALL FUNCTION 'M ...

  4. go语言简单的soap调用方法

    package main import ( "bytes" "encoding/xml" "fmt" "io" &quo ...

  5. ”position”之绝对定位深入理解

    要点: 1.绝对元素脱离文档流 它从文档流中脱离了出来,后面的元素会填充掉它原来的位置 2.绝对定位元素定位 以离他最近的.有定位的.祖先元素 为准 参照对象决定元素的位置 情况1 <div ( ...

  6. ImageLoader常用方法注释

    ImageLoader中的常用方法及相关作用注释 ImageLoader 的ImageLoaderConfiguration config 配置 ImageLoaderConfiguration co ...

  7. Object-C反射读取实体属性和值

    举例: 首先定义TestModel如下: @interface TestModel : NSObject @property (nonatomic, strong) NSString *name; @ ...

  8. Android中,Broadcas介绍

    什么是广播 在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制.我们拿广播电台来做个比方.我们平常使用收音机收音是这样的:许许多多不同的广播电台通过特定的频率来发送他们 ...

  9. python读xml文件

    # -*- coding:utf-8 -*- import jsonimport requestsimport os curpath=os.path.dirname(os.path.realpath( ...

  10. MySQL查询优化方法总结

    1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...