当前位置: 首页 > news >正文

设计模式之装饰者模式

基本介绍

装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)

模式原理

  1. 装饰者模式就像打包一个快递
    主体:比如:陶瓷、衣服 (Component) // 被装饰者
    包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator)
  2. Component 抽象主体,被装饰者,
  3. ConcreteComponent 具体的被装饰主体
  4. Decorator: 装饰者
    在如图的 Component 与 ConcreteComponent 之间,如果 ConcreteComponent 类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象层一个类。
    在这里插入图片描述

以星巴克咖啡订单为例运用装饰者模式

示例类图

在这里插入图片描述

示例代码

Component 抽象被修饰主体类

//饮品类
public abstract class Drink {
    private String des;
    private float price = 0.0f;

    public String getDes() {
        return des;
    }

    public void setDes(String des) {
        this.des = des;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    //计算费用的抽象方法
    //子类来实现
    public abstract float cost();
}

缓冲层咖啡类

//缓冲层咖啡类
public class Coffee extends Drink {
    @Override
    public float cost() {
        return super.getPrice();
    }
}

ConcreteComponent 具体被修饰主体类

//意大利咖啡类
public class Espresso extends Coffee {
    public Espresso() {
        setDes("意大利咖啡");
        setPrice(6.0f);
    }
}
//美式咖啡类
public class LongBlack extends Coffee {
    public LongBlack() {
        setDes("美国咖啡");
        setPrice(5.0f);
    }
}

装饰者

//佐料类
public class Decorator extends Drink {
    private Drink obj;

    public Decorator(Drink obj) {
        this.obj = obj;
    }

    @Override
    public float cost() {
        return super.getPrice() + obj.cost();
    }

    @Override
    public String getDes(){
        //输出被装饰者的信息
        return super.getDes() + ":" + super.getPrice() + " + " + obj.getDes();
    }
}

具体装饰者

//牛奶佐料类
public class Milk extends Decorator {
    public Milk(Drink obj) {
        super(obj);
        setDes("牛奶");
        setPrice(2.0f);
    }
}
//糖佐料类
public class Sugar extends Decorator {
    public Sugar(Drink obj) {
        super(obj);
        setDes("糖");
        setPrice(1.0f);
    }
}

客户端使用

public class CoffeeBar {
    public static void main(String[] args) {
        //1、点一杯意大利咖啡
        Drink order1 = new Espresso();
        System.out.println(order1.getDes()+" = "+order1.cost());
        //2、加奶
        order1 = new Milk(order1);
        System.out.println(order1.getDes()+" = "+order1.cost());
        //3、加糖
        order1 = new Sugar(order1);
        System.out.println(order1.getDes()+" = "+order1.cost());
        
       	System.out.println("=========================================");

        //1、点一杯美式咖啡
        Drink order2 = new LongBlack();
        System.out.println(order2.getDes()+" = "+order2.cost());
        //2、加两份奶
        order2 = new Milk(order2);
        order2 = new Milk(order2);
        System.out.println(order2.getDes()+" = "+order2.cost());
    }
}
//输出结果
//意大利咖啡 = 6.0
//牛奶:2.0 + 意大利咖啡 = 8.0
//糖:1.0 + 牛奶:2.0 + 意大利咖啡 = 9.0
//=========================================
//美国咖啡 = 5.0
//牛奶:2.0 + 牛奶:2.0 + 美国咖啡 = 9.0

使用装饰者模式之后,对于增加被装饰者或者增加装饰者都极为方便,只需要增加对应的类,被装饰者继承被装饰者的抽象类,装饰者继承装饰着的父类。不用改动代码,直接就可以在用户端使用,非常巧妙。

相关文章:

  • 一本“由厚变薄”的好书
  • 设计模式之组合模式
  • 设计模式之外观模式详解(Facade Pattern)
  • 优化系统七十项Reg文件
  • 设计模式之享元模式详解(FlyWeight Pattern)
  • 设计模式之代理模式详解(Proxy Pattern)
  • 又见林锐
  • 设计模式之模板方法模式详解(Template Method Pattern)
  • 工作苦旅
  • 设计模式之命令模式详解(Command Pattern)
  • 今天试用了VE开发SWT
  • 设计模式之访问者模式详解(Visitor Pattern)
  • GCC for Win32开发环境介绍(2)
  • 设计模式之观察者模式详解(Observer Pattern)
  • 设计模式之迭代器模式详解(Iterator Pattern)
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • LeetCode18.四数之和 JavaScript
  • mongodb--安装和初步使用教程
  • mysql_config not found
  • Python 反序列化安全问题(二)
  • Service Worker
  • Terraform入门 - 1. 安装Terraform
  • 翻译--Thinking in React
  • 移动端解决方案学习记录
  • 运行时添加log4j2的appender
  • 1.Ext JS 建立web开发工程
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • #include<初见C语言之指针(5)>
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (笔试题)分解质因式
  • (二)Eureka服务搭建,服务注册,服务发现
  • (附源码)springboot教学评价 毕业设计 641310
  • (论文阅读30/100)Convolutional Pose Machines
  • (译)计算距离、方位和更多经纬度之间的点
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • /etc/fstab和/etc/mtab的区别
  • @Tag和@Operation标签失效问题。SpringDoc 2.2.0(OpenApi 3)和Spring Boot 3.1.1集成
  • @在php中起什么作用?
  • [ C++ ] STL---string类的模拟实现
  • []我的函数库
  • [3D基础]理解计算机3D图形学中的坐标系变换
  • [8481302]博弈论 斯坦福game theory stanford week 1
  • [AutoSar]BSW_OS 02 Autosar OS_STACK
  • [BZOJ 1040] 骑士
  • [BZOJ4016][FJOI2014]最短路径树问题
  • [C#]手把手教你打造Socket的TCP通讯连接(一)
  • [C++] 如何使用Visual Studio 2022 + QT6创建桌面应用
  • [C++]——带你学习类和对象
  • [Go WebSocket] 多房间的聊天室(三)自动清理无人房间
  • [hihocoder1395] 最大权闭合子图
  • [HXPCTF 2021]includer‘s revenge