一、定义

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

    前段时间看spark,看着迷迷糊糊的.最近终于有点头绪,先梳理了一下spark rpc相关的东西,先记录下来. 1,概述 个人认为,如果把分布式系统(HDFS, HBASE,SPARK等)比作一个人, ...

  2. 【踩坑】Nginx上配置ssl证书实现https访问

    昨天开始为域名挂上ssl证书,使得可以以https去访问服务器.按照网上所介绍的配置Nginx,然而一直访问不了网站. 第二天排查了一早上,发现不单要配置Nginx,阿里云上安全组要开启443端口,并 ...

  3. w3c万维网的介绍和html基本构成

    怎么与浏览器交互? 1.鼠标 2.键盘输入 w3c标准: 中文名:万维网联盟!外文名:world wide web cansortium万维网联盟创建于1994年,是web技术领域最具权威个影响的国际 ...

  4. vue2.0:(八-2)、外卖App弹窗部分sticky footer

    什么是sticky-footer ? 如果页面内容不够长的时候,页脚块粘贴在视窗底部,如果内容足够长时,页脚块会被内容向下推送.那具体要怎么做呢?下面以外卖App为例: 第一种方法:这个自己用过,是好 ...

  5. 在使用添加按钮给table插入新的一行时遇见的问题总结及处理方法

    添加按钮的功能:点击添加按钮之后完成添加新的一行. 遇见的问题:当多次点击添加按钮生成新的多行之后,生成的每行内部按钮的保存按钮点击事件出现最晚添加的一行的行内保存点击事件执行一次,倒数第二次添加的行 ...

  6. Jenkins中启动从节点时,出现问题如何解决,问题:No Known Hosts...

    Jenkins中,启动从节点时,出现如下问题如何解决:/root/.ssh/known_hosts [SSH] No Known Hosts file was found at /root/.ssh/ ...

  7. 洛谷 P1433 吃奶酪

    题目描述 房间里放着n块奶酪.一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处. 输入输出格式 输入格式: 第一行一个数n (n<=15) 接下来每行2个实数,表示第i块 ...

  8. UWP开发:应用设置存储

    应用设置储存指的是保存在应用程序储存区中的键/值对的字典集合,它自动负责序列化对象,并将其保存在应用程序里.以键/值对方式提供一种快速数据访问的方式,主要用于储存一些应用信息. 1,简介 应用设置是W ...

  9. Android(java)学习笔记130:Android中操作XML数据(使用Pull解析器)

    1. Pull解析器的运行方式与 SAX 解析器相似.它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件.跟SAX不同的是, Pull解析器 ...

  10. 广播监听USB插入与拔出

    package com.joy.usbbroadcastreceiver; import android.content.BroadcastReceiver; import android.conte ...