设计模式-装饰器模式

简介: 设计模式-装饰器模式


装饰器模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活;它允许向一个现有的对象添加新的功能,同时又不改变其结构。装饰器模式属于结构型模式

UML 类图

  • Component:接口,定义一个抽象接口装饰对象与真实对象具有相同的接口,以便装饰器动态的添加职责。
  • ConcreteComponent: 接口的具体对象。
  • Decorator:装饰类,继承了 Component , 从外类来拓展 Component 的功能 并且持有一个 Component 的引用,通过构造器实例化,从而实现对真实对象的职责装饰增强。
  • ConcreteDecorator:具体装饰类,用于给实际对象添加职责。

使用场景

现在有一个场景:煎饼果子,科技园上班族早上去买煎饼果子(Pancake),有的人要加鸡蛋 (Egg)、有的人加火腿 (Ham)、有的人加生菜 (Lettuce)。有的土豪煎饼果子来一套全都要。现在我们来定义煎饼烹饪实现。(ps:留一个功能读者自己实现:不同的套餐价格是不一样的,如何计算出不同煎饼果子的价格?有兴趣的读者可以留言或者微信公众号后台留言)。

代码实现

代码可以左右滑动

  1. 先定义煎饼接口也就是我们的被装饰类,以及烹饪的方法 。
package com.zero.headfirst.decorator;
public interface Pancake {
    /**
     * 烹饪方法
     */
    void cook();
}
  1. 定义一个乞丐版煎饼,被装饰对象。
package com.zero.headfirst.decorator;
/**
 * 被装饰对象:定义最基本的乞丐版煎饼,啥都没加
 */
public class BeggarPancake implements Pancake {
    @Override
    public void cook() {
        System.out.println("乞丐版基本煎饼");
    }
}
  1. 定义抽象装饰类 煎饼果子装饰器 PancakeDecorator:抽象装饰器角色,实现煎饼接口(被装饰器接口),持有被装饰器的引用 (pancake)将烹饪行为转发具体的装饰器。
package com.zero.headfirst.decorator;
/**
 * 抽象装饰器角色,实现煎饼接口(被装饰器接口),持有被装饰器的引用将烹饪行为转发具体的装饰器。
 */
public abstract class PancakeDecorator implements Pancake {
    private Pancake pancake;
    public PancakeDecorator(Pancake pancake) {
        this.pancake = pancake;
    }
    @Override
    public void cook() {
        if (pancake != null) {
            pancake.cook();
        }
    }
}
  1. 各种具体装饰类对乞丐版煎饼进行不等级别的土豪加工。首先继承 抽象出来的 PancakeDecorator ,重写 cook 方法,实现加工。

EggDecorator 鸡蛋装饰器:继承 PancakeDecorator,重写 cook 方法。动态添加鸡蛋,然后调用pancake 的cook。

package com.zero.headfirst.decorator;
/**
 * 鸡蛋装饰器:覆盖cook方法,加入自身的实现,并且调用父类的cook方法,也就是构造函数中
 * EggDecorator(Pancake pancake),这里传入的pancake的cook操作
 */
public class EggDecorator extends PancakeDecorator {
    public EggDecorator(Pancake pancake) {
        super(pancake);
    }
    @Override
    public void cook() {
        System.out.println("加一个鸡蛋;");
        super.cook();
    }
}

火腿装饰器: HamDecorator

package com.zero.headfirst.decorator;
/**
 * 火腿装饰器
 */
public class HamDecorator extends PancakeDecorator {
    public HamDecorator(Pancake pancake) {
        super(pancake);
    }
    @Override
    public void cook() {
        System.out.println("加一个火腿;");
        super.cook();
    }
}

生菜装饰器

package com.zero.headfirst.decorator;
/**
 * 生菜装饰器
 */
public class LettuceDecorator extends PancakeDecorator {
    public LettuceDecorator(Pancake pancake) {
        super(pancake);
    }
    @Override
    public void cook() {
        System.out.println("加生菜;");
        super.cook();
    }
}
  1. 定义一个煎饼果子摊位。
package com.zero.headfirst.decorator;
/**
 * 煎饼果子店
 */
public class PancakeShop {
    public static void main(String[] args) {
        System.out.println("========土豪来了,全都加上。======");
        BeggarPancake beggarPancake = new BeggarPancake();
        EggDecorator eggDecorator = new EggDecorator(beggarPancake);
        HamDecorator hamAndEggDecorator = new HamDecorator(eggDecorator);
        LettuceDecorator lettuceAndHamAndEggDecorator = new LettuceDecorator(hamAndEggDecorator);
        lettuceAndHamAndEggDecorator.cook();
        System.out.println("========苦逼码农来了,只要鸡蛋补补脑。=====");
        BeggarPancake beggarPancake1 = new BeggarPancake();
        EggDecorator eggDecorator1 = new EggDecorator(beggarPancake1);
        eggDecorator1.cook();
    }
}
  1. 运行结果
========土豪来了,全都加上。======
加生菜;
加一个火腿;
加一个鸡蛋;
乞丐版基本煎饼
========苦逼码农来了,只要鸡蛋补补脑。=====
加一个鸡蛋;
乞丐版基本煎饼

总结

真实世界的装饰: Java I/O。

注意事项与要点

  • 抽象装饰器与具体被装饰对象实现同一个接口。
  • 抽象装饰器持有被装饰器接口对象,以便请求传递。
  • 具体装饰器需要重写抽象装饰器的方法并引用super进行条用,转发请求。

适用场景

  • 拓展一个类的功能。
  • 动态的添加与撤销职责。

优点

  • 装饰类与被装饰类只关心自己的核心逻辑,实现了解耦。
  • 方便动态拓展,开闭原则。且比继承灵活。

缺点

  • 如果功能拓展太多,将产生大量的类。
  • 多层装饰会变得复杂。


相关文章
|
7月前
|
设计模式 存储 缓存
聊聊Java设计模式-装饰器模式
装饰器模式允许向一个现有的对象添加新的功能,同时不改变其结果。比如Java 中的IO框架中,`FileInputStream`(处理文件)、`ByteArrayInputStream`(处理字节数组)、`BufferedInputStream`(带缓存的处理类)等就是对`InputStream`进行的功能扩展,这就是装饰器模式的典型应用。
63 1
聊聊Java设计模式-装饰器模式
|
7月前
|
设计模式 Java
常用设计模式(工厂方法,抽象工厂,责任链,装饰器模式)
有关设计模式的其他常用模式请参考 单例模式的实现 常见的设计模式(模板与方法,观察者模式,策略模式)
71 2
|
7月前
|
设计模式
设计模式之装饰器模式
设计模式之装饰器模式
|
7月前
|
设计模式
设计模式-装饰器模式
设计模式-装饰器模式
|
2月前
|
设计模式 XML Java
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
38 0
|
4天前
|
设计模式 前端开发 JavaScript
前端必须掌握的设计模式——装饰器模式
装饰器模式是一种结构型设计模式,通过创建新类来包装原始对象,实现在不修改原有结构的前提下扩展新行为。其核心在于“组合”思想,使新功能可“即插即拔”。该模式具有解耦性、灵活性和动态性等特点,广泛应用于类的面向对象编程语言中,如JavaScript的注解和TypeScript的写法。示例中,通过装饰器模式为游戏角色动态添加装备,展示了其强大的扩展性和灵活性。
|
7月前
|
设计模式 Java
Java一分钟之-设计模式:装饰器模式与代理模式
【5月更文挑战第17天】本文探讨了装饰器模式和代理模式,两者都是在不改变原有对象基础上添加新功能。装饰器模式用于动态扩展对象功能,但过度使用可能导致类数量过多;代理模式用于控制对象访问,可能引入额外性能开销。文中通过 Java 代码示例展示了两种模式的实现。理解并恰当运用这些模式能提升代码的可扩展性和可维护性。
69 1
|
3月前
|
设计模式 Java
Java设计模式-装饰器模式(10)
Java设计模式-装饰器模式(10)
|
6月前
|
设计模式 Java
Java设计模式:深入装饰器模式的三种写法(六)
Java设计模式:深入装饰器模式的三种写法(六)
|
6月前
|
设计模式 架构师 安全
设计模式第五讲-装饰器模式和代理模式详解
远程代理,这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中建立一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
275 0