From: https://liudongdong1.github.io/

装饰者模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。通常会定义一个抽象装饰类,而将具体的装饰类作为它的子类. 装饰模式的核心在于抽象装饰类的设计

  • 对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加。
  • Component(抽象构件):它是具体构件和抽象装饰类的共同父类声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
  • ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
  • Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
  • ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

1. Demo1

煎饼 加一个鸡蛋 加一个鸡蛋 加一根香肠, 销售价格: 12

public abstract class ABattercake {
protected abstract String getDesc();
protected abstract int cost();
}
public class Battercake extends ABattercake {
@Override
protected String getDesc() {
return "煎饼";
}
@Override
protected int cost() {
return 8;
}
}
  • 抽象装饰类,需要注意的是,抽象装饰类通过成员属性的方式将 煎饼抽象类组合进来,同时也继承了煎饼抽象类
public abstract class AbstractDecorator extends ABattercake {
private ABattercake aBattercake; public AbstractDecorator(ABattercake aBattercake) {
this.aBattercake = aBattercake;
} protected abstract void doSomething(); @Override
protected String getDesc() {
return this.aBattercake.getDesc();
}
@Override
protected int cost() {
return this.aBattercake.cost();
}
}
public class EggDecorator extends AbstractDecorator {
public EggDecorator(ABattercake aBattercake) {
super(aBattercake);
} @Override
protected void doSomething() { } @Override
protected String getDesc() {
return super.getDesc() + " 加一个鸡蛋";
} @Override
protected int cost() {
return super.cost() + 1;
} public void egg() {
System.out.println("增加了一个鸡蛋");
}
}

2. Demo2

下面需求开始:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:

具体需求:

1、武器(攻击力20) 、戒指(攻击力5)、护腕(攻击力5)、鞋子(攻击力5)

2、蓝宝石(攻击力5/颗)、黄宝石(攻击力10/颗)、红宝石(攻击力15/颗)

3、每个装备可以随意镶嵌3颗

package com.zhy.pattern.decorator;

/**
* 装备的接口
*
* @author zhy
*
*/
public interface IEquip
{ /**
* 计算攻击力
*
* @return
*/
public int caculateAttack(); /**
* 装备的描述
*
* @return
*/
public String description();
}
//Equip 实例
package com.zhy.pattern.decorator; /**
* 武器
* 攻击力20
* @author zhy
*
*/
public class ArmEquip implements IEquip
{ @Override
public int caculateAttack()
{
return 20;
} @Override
public String description()
{
return "屠龙刀";
} } //宝石超类 package com.zhy.pattern.decorator; /**
* 装饰品的接口
* @author zhy
*
*/
public interface IEquipDecorator extends IEquip
{
}
package com.zhy.pattern.decorator; /**
* 蓝宝石装饰品
* 每颗攻击力+5
* @author zhy
*
*/
public class BlueGemDecorator implements IEquipDecorator
{
/**
* 每个装饰品维护一个装备
*/
private IEquip equip; public BlueGemDecorator(IEquip equip)
{
this.equip = equip;
} @Override
public int caculateAttack()
{
return 5 + equip.caculateAttack();
} @Override
public String description()
{
return equip.description() + "+ 蓝宝石";
} }
package com.zhy.pattern.decorator;

public class Test
{
public static void main(String[] args)
{
// 一个镶嵌2颗红宝石,1颗蓝宝石的靴子
System.out.println(" 一个镶嵌2颗红宝石,1颗蓝宝石的靴子");
IEquip equip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));
System.out.println("攻击力 : " + equip.caculateAttack());
System.out.println("描述 :" + equip.description());
System.out.println("-------");
// 一个镶嵌1颗红宝石,1颗蓝宝石的武器
System.out.println(" 一个镶嵌1颗红宝石,1颗蓝宝石,1颗黄宝石的武器");
equip = new RedGemDecorator(new BlueGemDecorator(new YellowGemDecorator(new ArmEquip())));
System.out.println("攻击力 : " + equip.caculateAttack());
System.out.println("描述 :" + equip.description());
System.out.println("-------");
}
}

3. Java I/O中的装饰者模式

如果要实现一个自己的包装流,根据上面的类图,需要继承抽象装饰类 FilterInputStream,譬如来实现这样一个操作的装饰者类:将输入流中的所有小写字母变成大写字母

import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream; public class UpperCaseInputStream extends FilterInputStream {
protected UpperCaseInputStream(InputStream in) {
super(in);
} @Override
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toUpperCase(c));
} @Override
public int read(byte[] b, int off, int len) throws IOException {
int result = super.read(b, off, len);
for (int i = off; i < off + result; i++) {
b[i] = (byte) Character.toUpperCase((char) b[i]);
}
return result;
} public static void main(String[] args) throws IOException {
int c;
InputStream in = new UpperCaseInputStream(new FileInputStream("D:\\hello.txt"));
try {
while ((c = in.read()) >= 0) {
System.out.print((char) c);
}
} finally {
in.close();
}
}
}

4. spring cache 中的装饰者模式

public class TransactionAwareCacheDecorator implements Cache {
private final Cache targetCache; public TransactionAwareCacheDecorator(Cache targetCache) {
Assert.notNull(targetCache, "Target Cache must not be null");
this.targetCache = targetCache;
} public <T> T get(Object key, Class<T> type) {
return this.targetCache.get(key, type);
} public void put(final Object key, final Object value) {
// 判断是否开启了事务
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// 将操作注册到 afterCommit 阶段
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
public void afterCommit() {
TransactionAwareCacheDecorator.this.targetCache.put(key, value);
}
});
} else {
this.targetCache.put(key, value);
}
}
// ...省略...
}

5. spring session 中的装饰者模式

public class ServletRequestWrapper implements ServletRequest {    private ServletRequest request;        public ServletRequestWrapper(ServletRequest request) {        if (request == null) {            throw new IllegalArgumentException("Request cannot be null");        }        this.request = request;    }        @Override    public Object getAttribute(String name) {        return this.request.getAttribute(name);    }    //...省略...}

6. Mybatis 缓存中的装饰者模式

Resource

【设计模式】装饰者模式(DecoratorMode0的更多相关文章

  1. Java设计模式——装饰者模式

    JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...

  2. JAVA设计模式--装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...

  3. 从源码角度理解Java设计模式——装饰者模式

    一.饰器者模式介绍 装饰者模式定义:在不改变原有对象的基础上附加功能,相比生成子类更灵活. 适用场景:动态的给一个对象添加或者撤销功能. 优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个 ...

  4. 【设计模式】Java设计模式 - 装饰者模式

    Java设计模式 - 装饰者模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自 ...

  5. [Head First设计模式]山西面馆中的设计模式——装饰者模式

    引言 在山西面馆吃鸡蛋面的时候突然想起装饰者这个模式,觉得面馆这个场景跟书中的星巴兹咖啡的场景很像,边吃边思考装饰者模式.这里也就依葫芦画瓢,换汤不换药的用装饰者模式来模拟一碗鸡蛋面是怎么出来的吧.吃 ...

  6. JAVA 设计模式 装饰者模式

    用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式. 结构

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

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

  8. javascript设计模式——装饰者模式

    前面的话 在程序开发中,许多时候都并不希望某个类天生就非常庞大,一次性包含许多职责.那么可以使用装饰者模式.装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象.本文将 ...

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

    本文由@呆代待殆原创,转载请注明出处. 此设计模式遵循的设计原则之一:类应该支持扩展,而拒绝修改(Open-Closed Principle) 装饰者模式简述 装饰者模式通过组合的方式扩展对象的特性, ...

  10. C#设计模式--装饰器模式

    0.C#设计模式-简单工厂模式 1.C#设计模式--工厂方法模式 2.C#设计模式--抽象工厂模式 3.C#设计模式--单例模式 4.C#设计模式--建造者模式 5.C#设计模式--原型模式 6.C# ...

随机推荐

  1. Kotlin Coroutine(协程): 四、+ Retrofit

    @ 目录 前言 一.准备工作 二.开始使用 1.简单使用 2.DSL 3.扩展函数 4.请求发起 总结 前言 Retrofit 从 2.6.0 版本开始, 内置了对 Kotlin Coroutines ...

  2. [zebra源码]分片语句ShardPreparedStatement执行过程

    主要过程包括: 分库分表的路由定位 sql语句的 ast 抽象语法树的解析 通过自定义 SQLASTVisitor (MySQLSelectASTVisitor) 遍历sql ast,解析出逻辑表名 ...

  3. IP数据包格式与ARP转发原理

    一.网络层简介1.网络层功能2.网络层协议字段二.ICMP与封装三.ARP协议与ARP欺骗1.ARP协议2.ARP欺骗 1.网络层功能 1. 定义了基于IP地址的逻辑地址2. 连接不同的媒介3. 选择 ...

  4. python 得到字典的所有键 和值

    a={} a={"a":1,"b":2,"c":3,"d":4} print(a) print(a.items()) p ...

  5. Leetcode春季打卡活动 第二题:206. 反转链表

    Leetcode春季打卡活动 第二题:206. 反转链表 206. 反转链表 Talk is cheap . Show me the code . /** * Definition for singl ...

  6. 传统二三层转发融合SDN Openflow协议的Hybrid交换机转发流程

    Hybrid 交换系统(以下简称Hybrid 交换机)是交换机融合了OVS(Openflow vswitch)原生代码,集传统和Openflow 技术于一体的转发系统.主要解决纯Openflow 基于 ...

  7. 网络损伤仪WANsim的功能与型号

    网络损伤仪简介 WANsim网络损伤仪是一款可以模拟真实的广域网状况的设备.它可以通过简单的数据填写模拟出时延.带宽抖动.丢包.乱序.误码.报文重复等网络状况. 大多数公司在进行产品测试时,只关注了应 ...

  8. Matplotlib不能显示中文和正负号的问题

    参考链接:https://www.jianshu.com/p/240ea3ae0dc9 在使用matplotlib画饼状图时,遇到了如下问题 UserWarning: findfont: Font f ...

  9. 【对线面试官】Kafka基础入门

    <对线面试官>系列目前已经连载33篇啦,这是一个讲人话面试系列 [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 &am ...

  10. 每日三道面试题,通往自由的道路14——MySQL

    茫茫人海千千万万,感谢这一秒你看到这里.希望我的面试题系列能对你的有所帮助!共勉! 愿你在未来的日子,保持热爱,奔赴山海! 每日三道面试题,成就更好自我 昨天我们是不是聊到了锁,而你提到了MySQL? ...