设计模式(结构型设计模式——装饰者模式)

设计模式(结构型设计模式------装饰者模式)

装饰者模式

基本定义

装饰模式指的是在不必改变原类文件和使用继承(也是与适配器模式不一样的地方)的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

模式结构

Component: 抽象构件。是定义一个对象接口,可以给这些对象动态地添加职责。

ConcreteComponent:具体构件。是定义了一个具体的对象,也可以给这个对象添加一些职责。

Decorator:抽象装饰类。是装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator存在的。

ConcreteDecorator:具体装饰类,起到给Component添加职责的功能。

代码实现

Component:抽象构件, 被装饰抽象类
java 复制代码
public interface Cake {
    String nameDetail();
    Double price();
}
ConcreteComponent: 抽象实现类,被装饰对象类
java 复制代码
public class CakeImpl implements Cake {
    /**
     * 手抓饼配料->鸡蛋,牛肉,蔬菜,
     * 组合方式:1.鸡蛋,2.牛肉,3.蔬菜,4. 鸡蛋+牛肉,5. 鸡蛋+蔬菜,6.牛肉+蔬菜, 7.鸡蛋+牛肉+蔬菜
     */
    public String nameDetail() {
        return "原味手抓饼";
    }
    public Double price() {
        return 5d;
    }
}
Decorator: 抽象装饰类
java 复制代码
public class CakeDecorator implements Cake{
    Cake cake;
    //装饰实现类
    public CakeDecorator(Cake cake) {
        this.cake = cake;
    }
    public String nameDetail() {
        return cake.nameDetail();
    }
    public Double price() {
        return cake.price();
    }
}
ConcreteDecorator: Decorator具体实现类

鸡蛋手抓饼 +1.5元

java 复制代码
public class EggCakeDecorator extends CakeDecorator{
    public EggCakeDecorator(Cake cake) {
        super(cake);
    }
    //关键部分
    @Override
    public String nameDetail() {
        return "鸡蛋," + cake.nameDetail();
    }
    @Override
    public Double price() {
        return 1.5 + cake.price();
    }
}

牛肉手抓饼 +2元

java 复制代码
public class MeetCakeDecorator extends CakeDecorator{

    public MeetCakeDecorator(Cake cake) {
        super(cake);
    }

    //关键部分
    @Override
    public String nameDetail() {
        return "牛肉," + cake.nameDetail();
    }
    @Override
    public Double price() {
        return 2 + cake.price();
    }
}

蔬菜手抓饼 +0.5元

java 复制代码
public class VeggCakeDecorator extends CakeDecorator{

    public VeggCakeDecorator(Cake cake) {
        super(cake);
    }

    //关键部分

    @Override
    public String nameDetail() {
        return "蔬菜," + cake.nameDetail();
    }

    @Override
    public Double price() {
        return 0.5 + cake.price();
    }
}
测试类
java 复制代码
@Slf4j
public class Test {

    public static void main(String[] args) {
        Cake cake = new CakeImpl();
        log.info("小红想吃{}, 价格:¥{}", cake.nameDetail(), cake.price());

        CakeDecorator cakeEgg = new EggCakeDecorator(cake);
        log.info("小明想吃{}, 价格:¥{}", cakeEgg.nameDetail(), cakeEgg.price());

        CakeDecorator meetCake = new MeetCakeDecorator(cakeEgg);
        CakeDecorator veggCake = new VeggCakeDecorator(meetCake);
        log.info("小张想吃{}, 价格:¥{}", veggCake.nameDetail(), veggCake.price());
    }
}

优点

  1. 装饰者模式可以提供比继承更多的灵活性。

  2. 可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。

  3. 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。

  4. 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合"开闭原则"。

缺点

  1. 会产生很多的小对象,增加了系统的复杂性

  2. 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

使用场景

  1. 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  2. 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。
相关推荐
爱读源码的大都督20 分钟前
为什么有了HTTP,还需要gPRC?
java·后端·架构
qq_49244844629 分钟前
Jmeter设置负载阶梯式压测场景(详解教程)
开发语言·python·jmeter
Lucky_Turtle39 分钟前
【Java Xml】Apache Commons Digester3解析
xml·java·apache
聪明的笨猪猪1 小时前
Java Redis “缓存设计”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
FIavor.1 小时前
我发送给Apifox是http://localhost:9002/goods/getByUserName?name=张三 为什么会是500哪里错了?
java·服务器·网络协议·http
ID_180079054731 小时前
京东获取整站实时商品详情数据|商品标题|数据分析提取教程
java·开发语言
微露清风2 小时前
系统性学习C++-第五讲-内存管理
java·c++·学习
计算机毕业设计木哥2 小时前
计算机毕业设计选题推荐:基于SpringBoot和Vue的快递物流仓库管理系统【源码+文档+调试】
java·vue.js·spring boot·后端·课程设计
qiuiuiu4132 小时前
正点原子RK3568学习日志-编译第一个驱动程序helloworld
linux·c语言·开发语言·单片机
235162 小时前
【LeetCode】146. LRU 缓存
java·后端·算法·leetcode·链表·缓存·职场和发展