设计模式——装饰者模式(继承和接口的两种实现方式)

news2024/11/16 18:31:09

是什么?

场景案例:想必大家都吃过手抓饼吧,我们在点手抓饼的时候可以选择加培根、鸡蛋、火腿、肉松等等这些配菜,当然这些配菜的价格都不一样,那么计算总价就比较麻烦;

装饰者模式就是指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即额外功能);

结构

抽象构件:定义一个抽象接口以规范准备接收附加责任的对象;

具体构件:实现抽象构件,通过装饰角色为其添加一些职责;

抽象装饰:继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能;

具体装饰:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任;

实现

通过继承

抽象构件

public abstract class HandGraspStore {
    //手抓饼店铺==>抽象构建
    private float price;
    private String desc;

    public HandGraspStore() {

    }

    public HandGraspStore(float price, String desc) {
        this.price = price;
        this.desc = desc;
    }

    public Float getPrice() {
        return price;
    }

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

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
    public abstract float cost();
}

具体构件

public class HandGraspCake extends HandGraspStore{
    //手抓饼===>具体构件

    public HandGraspCake() {
        super(10,"手抓饼");
    }

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

抽象装饰

public abstract class Decorator extends HandGraspStore {
    //抽象装饰
    private HandGraspStore handGraspStore;

    public HandGraspStore getHandGraspStore() {
        return handGraspStore;
    }

    public void setHandGraspStore(HandGraspStore handGraspStore) {
        this.handGraspStore = handGraspStore;
    }

    public Decorator(HandGraspStore handGraspStore,float price,String desc) {
        super(price,desc);
        this.handGraspStore=handGraspStore;
    }
}

具体装饰

public class Egg extends Decorator{
    //鸡蛋===>具体装饰
    public Egg(HandGraspStore handGraspStore) {
        super(handGraspStore,1,"加一个鸡蛋");
    }

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

    @Override
    public String getDesc() {
        return super.getDesc()+getHandGraspStore().getDesc();
    }
}
public class Ham extends Decorator{
    //培根===>具体装饰
    public Ham(HandGraspStore handGraspStore) {
        super(handGraspStore,3,"加一个火腿");
    }

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

    @Override
    public String getDesc() {
        return super.getDesc()+getHandGraspStore().getDesc();
    }
}

用户使用

public class Customer {
    public static void main(String[] args) {
        HandGraspCake handGraspCake = new HandGraspCake();
        System.out.println(handGraspCake.getDesc()+handGraspCake.getPrice()+"元");
        System.out.println("==============================");
        Egg egg = new Egg(handGraspCake);
        System.out.println(egg.getDesc()+egg.cost()+"元");
        System.out.println("===============================");
        Ham ham = new Ham(egg);
        System.out.println(ham.getDesc()+ham.cost()+"元");
    }
}

通过接口

抽象构件

public interface IHandGraspCakeStore {
    float price();
    String desc();
    float cost();
}

 具体构件

public class IHandGraspStore implements IHandGraspCakeStore {
    @Override
    public float price() {
        return 10;
    }

    @Override
    public String desc() {
        return "手抓饼";
    }

    @Override
    public float cost() {
        return price();
    }
}

抽象装饰

public interface IDecoratorStore extends IHandGraspCakeStore {

}

具体装饰

public class IEggStore implements IDecoratorStore {

    private IHandGraspCakeStore handGraspCake;

    public IEggStore(IHandGraspCakeStore handGraspCake) {
        this.handGraspCake=handGraspCake;
    }



    @Override
    public float price() {
        return 1;
    }

    @Override
    public String desc() {
        return handGraspCake.desc()+"加鸡蛋";
    }

    @Override
    public float cost() {
        return price()+ handGraspCake.cost();
    }
}

用户使用

public class ICustomerDemo {
    public static void main(String[] args) {
        IHandGraspStore iHandGrasp = new IHandGraspStore();
        System.out.println(iHandGrasp.desc()+iHandGrasp.cost()+"元");
        System.out.println("================================");
        IEggStore iEgg = new IEggStore(iHandGrasp);
        System.out.println(iEgg.desc()+iEgg.cost()+"元");
        IEggStore eg = new IEggStore(iEgg);
        System.out.println(eg.desc()+eg.cost()+"元");
    }
}

 我们可以发现,这其实是一个反向控制,也就是说用户最终得到的是一个具体装饰类,而非我们的具体构建类,因为最终的金额计算或者说其他的操作逻辑,都是在具体装饰中进行统计并完成的;

优点

        1.装饰者模式可以带来比继承更加灵活性的扩展功能,使用更加方便,可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化的结果,装饰者模式比继承更具有良好的扩展性,完美的尊姓开闭原则,继承是静态的附加责任,装饰者则是动态的附加责任

        2.装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能

使用场景

1.当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时;

     不能采用继承的情况主要有以下两种:

        第一种是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;

        第二种是因为类不能继承(例如final类)

2.在不影响其他对象的情况下,需要以动态、透明的方式给单个对象添加职责;

3.当对象的功能要求可以动态地添加,也可以再动态地撤销时;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/496727.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot 集成 shardingSphere 加mybatisplus 自带增加 分页查询 和源代码包 分库分表 单库 分表 使用雪花算法id

目录 介绍 代码下载 效果 数据库 代码结构 上代码 pom.xml yml配置 建表语句 mapper.xml mybatisplus 配置.java logback application.java BaseEntity TUser TUserMapper TUserService TUserServiceImpl TUserController 测试 介绍 这套springboot shardi…

OSG笔记:AutoTransform实现固定像素大小的图形

需求 在(200,0,0)位置绘制固定10像素大小的正方体 实现方式 为了便于观察,例子中绘制了两条直线,相交于(200,0,0)。 //两根直线交于(200, 0, 0),用于辅助观察 {osg::Geometry* pLineGeom new osg::Geometry();osg::Vec3Array* pVertexArra…

python语法复习

print:输出函数 print(520)效果:输出520. print(hello)效果:输出hello. print(1020)【效果:输出了:1020】注:“ ”在print里面是一个连接符。 print(1020)【效果:输出了30】注: 在此处…

OJ 系统常用功能介绍 快速入门 C++ Python JAVA语言在线评测

技术支持微 makytony 服务器配置 腾讯云 2H4G 5M 60GB 轻量应用服务器 承载大约 200~400人使用,经过压力测试,评测并发速度可满足130人左右的在线比赛。 系统镜像选 Ubuntu 22.04 LTS ,Ubuntu是最热门的Linux发行版之一,是一款…

洞车系统常见问题解决指南

洞车常见问题解决指南 1.研发脚本处理问题1.1 WMS出库单无法审核1.2 OMS入库单无法提交,提示更新中心库存失败1.3 当出现OMS下发成功WMS/TMS/DMS还没有任务的情况时处理方案1.4 调度波次生成或者添加任务系统异常1.5 东鹏出库单部分出库回传之后要求重传1.6 更新订单…

spring、springmvc、springboot、mybatis框架高频面试题

一、spring 1、Spring框架中的单例bean是线程安全的吗? 不是线程安全的,是这样的: 当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求对应的业务逻辑(成员方法&a…

ES索引结构升级-笔记

ES中索引的字段类型是不可修改的,只能是重新创建一个索引并设置好mapping,然后再将老索引的数据复制过去 查看老索引mapping GET /twitter/_mappings创建new索引,并指定mapping PUT /twitter410{"mappings": {"properties&…

金3银四结束了,回顾一下我2个月面试的公司....

金三银四结束了,还没有 offer 的同学不要气馁,该来的迟早会来。楼主从 年底 月有想法跳槽开始准备春招,一开始也是惨不忍睹,后来慢慢进入状态最近的面试基本都能走到终面,所以好好坚持,最后一定会有好结果的…

操作系统考试复习——第四章 存储器管理 4.1 4.2

存储器的层次结构: 存储器的多层结构: 存储器至少分为三级:CPU寄存器,主存和辅存。 但是一般分为6层为寄存器,高速缓存,主存储器,磁盘缓存,固定磁盘,可移动存储介质。…

无需重复造轮子—借助 Jetpack 组件,加速应用程序开发

简介 Android Jetpack 是谷歌官方推出的一套 Android 应用架构组件库,旨在为 Android 应用开发提供一种更优秀、更高效且更简单的方式。 Android Jetpack 对开发者带来了许多好处,以下是其中的一些: 提高开发效率:Jetpack 提供…

vue项目重复点击一个路由会报错如何解决

在新版本的vue-router中,重复点击同一个路由会出现以下报错 : 这个问题时vue-router 3.2.0版本的一个小Bug 方法有很多,比如降低路由版本(不推荐),但是推荐下面这种方式,比较简单靠谱 // 把这段代码直接粘贴到router/index.js中的Vue.use(VueRouter)之…

django:django2配置websocket

源码地址: https://gitee.com/liuhaizhang/django2-configuring-websockethttps://gitee.com/liuhaizhang/django2-configuring-websocket python3.9.0 django2.2.1 channels2.2.0 项目结构: test_websocket_django2 -chat -home -test_websocket_dja…

深度学习笔记之卷积神经网络(一)卷积函数与图像卷积操作

深度学习笔记之卷积神经网络——卷积函数 引言什么是卷积图像卷积操作 引言 从本节开始,将介绍卷积神经网络。本节将介绍卷积函数。 什么是卷积 卷积,是一种通过两个函数 f ( ⋅ ) 和 f(\cdot)和 f(⋅)和 g ( ⋅ ) g(\cdot) g(⋅)生成第三个函数 h ( …

备战花了2个月,春招3轮顺利拿下字节offer

PART1:个人情况简介 菜 J 一枚,本硕都是计算机(普通二本),2021 届应届硕士,软件测试方向。个人也比较喜欢看书,技术书之类的都有看,最后下面也会推荐一些经典书籍。 先说一下春招结…

Docker--harbor私有仓库管理与部署

目录 一、本地私有仓库 搭建本地私有仓库 Docker容器的重启策略 二、Harbor 1、什么是Harbor 2、Harbor特性 3、Harbor的构成 三、Harbor部署 实验步骤 1、安装Docker-Compose服务 2、部署Harbor服务 1、下载或上传Harbor安装程序 2、修改Harbor安装的配置文件 3、…

day26_mysql

今日内容 零、 复习昨日 一、MySQL 一、引言 1.1 现有的数据存储方式有哪些? Java程序存储数据(变量、对象、数组、集合),数据保存在内存中,属于瞬时状态存储。 文件(File)存储数据&#xff0c…

多款智能骑行终端齐登场,移远通信闪亮第31届中国国际自行车展览会

近年来,自行车、电动车市场火爆,随着数字化、智能化的持续深入,更具科技感的骑行工具受到了越来越多年轻一代的青睐。5月5-8日,以" 更安全、更智能、更低碳 " 为主题的第 31 届中国国际自行车展览会在上海新国际博览中心…

Java连接顺丰开放平台

今天使用Java去访问顺丰的开放平台时,JSON转换一直不成功,最终发现是 可以看到这里是 "apiResultData": "{\"success\": .........它是以 " 开头的!!!如果是对象的话,那么…

Zookeeper初识

序 Zookeeper是什么,Zookeeper有什么用?因为在研究Zookeeper源码之后,就要去研究Dubbo源码,而Dubbo必然用到了Zookeeper,而我在写这篇博客时,我也是一个Zookeeper小白,我也有7年开发经验了&…

将ROS1和ROS2安装到同一个ubuntu系统中,ROS2安装

1. 本文测试环境: ubuntu:20.04,虚拟机 ROS1:noetic ROS2:foxy 2. 先说结论 ROS1 与 ROS2 共存,需要考虑三个问题: 1) 不同Ubuntu版本,有不同版本的ROS1和ROS2推荐,尽量不要任性地乱装; 2)ROS1和ROS2安装过程中,是否会出现文件“删改”的问题?目前使用下来,并…