本文源码:GitHub·点这里 || GitEE·点这里

一、生活场景

1、场景描述

孙悟空有七十二般变化,他的每一种变化都给他带来一种附加的本领。他变成鱼儿时,就可以到水里游泳;他变成鸟儿时,就可以在天上飞行。

2、场景图解

3、代码实现

public class C01_InScene {
public static void main(String[] args) {
TheGreatestSage greatestSage = new Monkey();
TheGreatestSage fish = new Fish(greatestSage);
fish.shapeDesc();
// 这里虽然是鱼形态,但是本体是悟空,所以可以直接变化
TheGreatestSage bird = new Bird(fish);
bird.shapeDesc();
}
}
// 顶级接口
interface TheGreatestSage {
// 定义一个描述形态的方法
void shapeDesc ();
}
// 悟空本尊
class Monkey implements TheGreatestSage{
@Override
public void shapeDesc() {
System.out.println("Monkey.move()");
}
}
// 包装一层变化的描述
class Change implements TheGreatestSage {
private TheGreatestSage greatestSage;
Change(TheGreatestSage greatestSage){
this.greatestSage = greatestSage;
}
@Override
public void shapeDesc() {
greatestSage.shapeDesc();
}
}
// 具体的变化形态
class Fish extends Change{
public Fish(TheGreatestSage greatestSage) {
super(greatestSage);
}
public void shapeDesc(){
System.out.println("鱼在水中游...");
}
}
class Bird extends Change{
public Bird(TheGreatestSage greatestSage) {
super(greatestSage);
}
public void shapeDesc(){
System.out.println("鸟在空中飞...");
}
}

二、装饰模式

1、基础概念

装饰模式又名包装(Wrapper)模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。

2、核心角色

  • 抽象构件角色

给出一个抽象接口,以规范准备接收附加责任的对象。

  • 具体构件角色

定义一个将要接收附加责任的类。

  • 装饰角色

持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。

  • 具体装饰角色

负责给构件对象“贴上”附加的责任。

3、模式图解

4、源代码实现

// 抽象构件角色
interface Component {
void sampleOperation();
}
// 具体构件角色
class ConcreteComponent implements Component{
@Override
public void sampleOperation() {
System.out.println("业务相关代码");
}
}
//装饰角色
class Decorator implements Component{
private Component component;
public Decorator(Component component){
this.component = component;
}
@Override
public void sampleOperation() {
//委派给构件进行处理
component.sampleOperation();
}
}
// 具体装饰角色
class ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void sampleOperation() {
super.sampleOperation();
System.out.println("A.处理相关业务的代码");
}
}
class ConcreteDecoratorB extends Decorator{
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void sampleOperation() {
super.sampleOperation();
System.out.println("B.处理相关业务方法");
}
}

5、该模式简化

  • 简化抽象类

如果只有一个ConcreteComponent类,那么可以考虑去掉抽象的Component类(接口),把Decorator作为一个ConcreteComponent子类。

  • 简化装饰类

如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

6、半透明说明

1)、纯粹的装饰模式很难找到。装饰模式的用意是在不改变接口的前提下,增强类的功能。

2)、在增强功能的时候,往往需要建立新的公开的方法。

3)、这就导致了大多数的装饰模式的实现都是“半透明”的,而不是完全透明的。换言之,允许装饰模式改变接口,增加新的方法。这意味着客户端可以声明ConcreteDecorator类型的变量,从而可以调用ConcreteDecorator类中才有的方法。

4)、半透明的装饰模式是介于装饰模式和适配器模式之间的。适配器模式的用意是改变类的接口,也可以通过改写一个或几个方法,或增加新的方法来增强类的功能。

5)、大多数的装饰模式实际上是半透明的装饰模式,这样的装饰模式也称做半装饰、半适配器模式。

三、实际应用

1、JDK中IO流

1)、基本描述

装饰模式在Java语言中的最经典的应用就是Java I/O类库的设计。很少单一的创建流对象,通过创建多个叠合对象来提供所期望的IO流功能,因此装饰模式是Java I/O类库的基本模式。

2)、IO流图解描述

  • 抽象构件角色

由InputStream扮演。这是一个抽象类,为各种子类型提供统一的接口。

  • 具体构件角色

由FileInputStream、StringBufferInputStream等类扮演。它们实现了抽象构件角色所规定的接口。

  • 抽象装饰角色

由FilterInputStream扮演。它实现了InputStream所规定的接口。

  • 具体装饰角色

由几个类扮演,分别是BufferedInputStream、DataInputStream以及两个不常用到的类LineNumberInputStream、PushbackInputStream。

四、优缺点总结

1、模式的优点

(1)装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者除掉一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了。

(2)通过使用不同的具体装饰类以及这些装饰类的排列组合,工程师可以创造出很多不同行为的组合。

2、模式的优点

由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。

五、源代码地址

GitHub地址:知了一笑
https://github.com/cicadasmile/model-arithmetic-parent
码云地址:知了一笑
https://gitee.com/cicadasmile/model-arithmetic-parent

Java描述设计模式(09):装饰模式的更多相关文章

  1. Java IO设计模式(装饰模式与适配器模式)

    01. 装饰模式 1. 定义 Decorator装饰器,就是动态地给一个对象添加一些额外的职责,动态扩展,和下面继承(静态扩展)的比较.因此,装饰器模式具有如下的特征: 它必须持有一个被装饰的对象(作 ...

  2. Java描述设计模式(11):观察者模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.观察者模式 1.概念描述 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.观察者模式定义了一种一对多 ...

  3. Java描述设计模式(15):责任链模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景描述 1.请假审批流程 公司常见的请假审批流程:请假天数 当 day<=3 天,项目经理审批 当 3<day<= ...

  4. Java描述设计模式(24):备忘录模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景 1.场景描述 常见的视频播放软件都具备这样一个功能:假设在播放视频西游记,如果这时候切换播放视频红楼梦,当再次切回播放西游记时, ...

  5. Java描述设计模式(12):外观模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景 1.场景描述 在移动互联网没有普及之前,去饭店吃饭的流程大致如下:选座位,排队,点菜,结账.后来移动互联网普及,通过手机APP就 ...

  6. Java描述设计模式(08):桥接模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.桥接模式简介 1.基础描述 桥梁模式是对象的结构模式.又称为柄体(Handle and Body)模式或接口(Interface)模式.桥 ...

  7. Java描述设计模式(05):原型模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.原型模式简介 1.基础概念 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出 ...

  8. Java描述设计模式(03):工厂方法模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.工厂方法模式 1.生活场景 系统常见的数据导出功能:数据导出PDF.WORD等常见格式. 2.工厂方法模式 是类的创建模式,又叫做虚拟构造 ...

  9. Java描述设计模式(02):简单工厂模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景简介 1.引入场景 订餐流程简单描述 1).食品抽象类,规定食品的基础属性操作 2).鱼类,鸡肉类食品类扩展 3).订餐流程类,根 ...

随机推荐

  1. python基础入门 字典

    字典 字典---->dict 字典是无序的,可变的 关联性强 键值对 键:使用不可变的数据类型(可哈希),键是唯一的 值:可以任意 定义一个字典 dic = {}#定义字典 ​ 字典的增删改查 ...

  2. Docker swarm实战总结

    一.简介 Swarm 是 Docker 官方提供的一款集群管理工具,其主要作用是把若干台 Docker 主机抽象为一个整体,并且通过一个入口统一管理这些 Docker 主机上的各种 Docker 资源 ...

  3. 建议2:注意Javascript数据类型的特殊性---(3)正确检测数据类型

    使用typeof预算符返回一个用于识别其运算数类型的字符串.对于任何变量来说,使用typeof预算符总是以字符串的形式返回一下6种类型之一 number string boolean object f ...

  4. hexo + next 搭建博客时Cannot GET /tags/问题处理

    原来是要修改新建的index.md文件,不仔细. 此外,愈发觉得百度和谷歌搜索同一问题的差距,谷歌更适合程序员! https://www.zhihu.com/question/29017171 这个可 ...

  5. Java语法进阶10-泛型

    泛型 泛型:参数化的类型,即把数据类型当做参数来传递 有的地方又称为泛化的类型,用一个单个大写字母,例如<T>来代表任意类型,这个T就是泛化的类型. 泛型的好处: (1)表示某个变量的类型 ...

  6. Python操作MySQL的一些坑

    pip安装库时遇到的问题   我使用ubuntu系统通过pip安装MySQLdb库的时候,报了一堆错,解决了半天,没搞定.然后安装另一个库pymysql一下就OK了,它们的功能都是一样的.这个问题我没 ...

  7. 如何从Mac删除恶意广告软件,摆脱那些通过弹出广告或工具栏入侵Mac的恶意软件

    厌倦了那些利用弹出式广告和工具栏之类入侵Mac的恶意软件?该如何摆脱Mac上的恶意软件呢?今天小编为大家带来两种方法从Mac 删除广告软件,甚至阻止它到达您的Mac,感兴趣的朋友一起来看看吧! 方法一 ...

  8. gohook 一个支持运行时替换 golang 函数的库实现

    运行时替换函数对 golang 这类静态语言来说并不是件容易的事情,语言层面的不支持导致只能从机器码层面做些奇怪 hack,往往艰难,但如能成功,那挣脱牢笼带来的成就感,想想就让人兴奋. gohook ...

  9. vue组件常用声明方式

    一.前言 这是自己重新写的一个,感觉以前的太写了很多不必要的方式 实际当中基本不会用的 所以自己写了一个常用的组件什么方式 更加的通俗易懂 二.代码如下 <!DOCTYPE html> & ...

  10. IPFS学习-内容标识符(CIDs)

    内容标识符(CIDs) 内容标识符也称为CID,是用于指向IPFS中材料的标签. 它不会指示内容的存储位置,但会根据内容本身形成一种地址. CID简短,无论其基础内容的大小如何. CID基于内容的加密 ...