Java设计模式-装饰者模式

目录

一、星巴克咖啡订单项目

二、装饰者模式

(一)定义

(二)原理

(三)装饰者模式解决星巴克咖啡订单


一、星巴克咖啡订单项目

星巴克咖啡订单项目(咖啡馆):
1) 咖啡种类 / 单品咖啡: Espresso( 意大利浓咖啡 ) ShortBlack LongBlack( 美式咖啡) Decaf( 无因咖啡 )
2) 调料: Milk Soy( 豆浆 ) Chocolate
3) 要求在扩展 新的咖啡种类 时,具有良好的扩展性、改动方便、维护方便
4) 使用 OO 的来计算不同种类咖啡的 费用 : 客户可以点 单品咖啡 ,也可以 单品咖 + 调料组合

方案一:

1) Drink 是一个抽象类,表示饮料
2) des 就是对咖啡的描述 , 比如咖啡的名字
3) cost() 方法就是计算费用, Drink 类中做成一个抽象方法 .
4) Decaf 就是单品咖啡, 继承 Drink, 并实现 cost
5) Espress && Milk 就是单品咖啡 + 调料, 这个组合很多
6) 问题:这样设计,会有很多类,当我们增加一个单品咖啡,或者一个新的调料,类的数量就会倍增,就会出现类爆炸

方案二:

前面分析到方案 1 因为 咖啡单品 + 调料 组合会造成类的倍增,因此可以做改进,将调料内置到Drink 类,这样就 会造成类数量过多 。从而提高项目的维护性
1) 方案 2 可以控制类的数量,不至于造成很多的类
2) 增加或者删除调料种类 时,代码的维护量很大
3) 考虑到用户可以添加多份 调料时,可以将 hasMilk 返回一个对应 int
4) 考虑使用 装饰者 模式

二、装饰者模式

(一)定义

1) 装饰者模式: 动态的 将新功能 附加到对象上 。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)
2) 这里提到的 动态的将新功能附加到对象 ocp 原则 ,在后面的应用实例上会以代码的形式体现,请同学们注意体会

(二)原理

1) 装饰者模式就像 打包一个快递
①   主体:比如:陶瓷、衣服 (Component) // 被装饰者
②   包装:比如:报纸填充、塑料泡沫、纸板、木板 (Decorator)
2) Component
        主体:比如类似前面的Drink
3) ConcreteComponent Decorator
        ConcreteComponent:具体的主体, 比如前面的各个单品咖啡
        Decorator: 装饰者,比如各调料 .
4) 在如图的 Component ConcreteComponent 之间 ,如果 ConcreteComponent类很多 , 还可以设计一个缓冲层,将共有的部分提取出来, 抽象成一个类。

(三)装饰者模式解决星巴克咖啡订单

代码实现:
Drink

public abstract class Drink {

	public 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();
	
}

 coffee

public class Coffee  extends Drink {

	@Override
	public float cost() {
		// TODO Auto-generated method stub
		return super.getPrice();
	}

	
}

几种咖啡

public class DeCaf extends Coffee {

	public DeCaf() {
		setDes(" 无因咖啡 ");
		setPrice(1.0f);
	}
}

======================================
public class Espresso extends Coffee {
	
	public Espresso() {
		setDes(" 意大利咖啡 ");
		setPrice(6.0f);
	}
}

======================================
public class LongBlack extends Coffee {

	public LongBlack() {
		setDes(" longblack ");
		setPrice(5.0f);
	}
}

装饰类Decorator,也是继承Drink,内部有一个被装饰类Drink

public class Decorator extends Drink {
	private Drink obj;
	
	public Decorator(Drink obj) { //组合
		// TODO Auto-generated constructor stub
		this.obj = obj;
	}
	
	@Override
	public float cost() {
		// TODO Auto-generated method stub
		// getPrice 自己价格
		return super.getPrice() + obj.cost();
	}
	
	@Override
	public String getDes() {
		// TODO Auto-generated method stub
		// obj.getDes() 输出被装饰者的信息
		return des + " " + getPrice() + " && " + obj.getDes();
	}

}

具体的装饰类,这里是几种调料

//具体的Decorator, 这里就是调味品
public class Chocolate extends Decorator {

	public Chocolate(Drink obj) {
		super(obj);
		setDes(" 巧克力 ");
		setPrice(3.0f); // 调味品 的价格
	}

}

==========================================
public class Milk extends Decorator {

	public Milk(Drink obj) {
		super(obj);
		// TODO Auto-generated constructor stub
		setDes(" 牛奶 ");
		setPrice(2.0f); 
	}

}


==========================================
public class Soy extends Decorator{

	public Soy(Drink obj) {
		super(obj);
		// TODO Auto-generated constructor stub
		setDes(" 豆浆  ");
		setPrice(1.5f);
	}

}

装饰者模式下的订单: 2 份巧克力 + 一份牛奶的 LongBlack
public class CoffeeBar {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 装饰者模式下的订单:2份巧克力+一份牛奶的LongBlack

		// 1. 点一份 LongBlack
		Drink order = new LongBlack();
		System.out.println("费用1=" + order.cost());
		System.out.println("描述=" + order.getDes());

		// 2. order 加入一份牛奶
		order = new Milk(order);

		System.out.println("order 加入一份牛奶 费用 =" + order.cost());
		System.out.println("order 加入一份牛奶 描述 = " + order.getDes());

		// 3. order 加入一份巧克力

		order = new Chocolate(order);

		System.out.println("order 加入一份牛奶 加入一份巧克力  费用 =" + order.cost());
		System.out.println("order 加入一份牛奶 加入一份巧克力 描述 = " + order.getDes());

		// 3. order 加入一份巧克力

		order = new Chocolate(order);

		System.out.println("order 加入一份牛奶 加入2份巧克力   费用 =" + order.cost());
		System.out.println("order 加入一份牛奶 加入2份巧克力 描述 = " + order.getDes());
	
		System.out.println("===========================");
		
		Drink order2 = new DeCaf();
		
		System.out.println("order2 无因咖啡  费用 =" + order2.cost());
		System.out.println("order2 无因咖啡 描述 = " + order2.getDes());
		
		order2 = new Milk(order2);
		
		System.out.println("order2 无因咖啡 加入一份牛奶  费用 =" + order2.cost());
		System.out.println("order2 无因咖啡 加入一份牛奶 描述 = " + order2.getDes());

	
	}

}

Java IO 结构, FilterInputStream 就是一个装饰者模式
public abstract class InputStream implements Closeable{} //是一个抽象类,即Component
public class FilterInputStream extends InputStream { //是一个装饰者类Decorator
    protected volatile InputStream in //被装饰的对象 
}
class DataInputStream extends FilterInputStream implements DataInput { //FilterInputStream 子类, 也继承了被装饰的对象in 
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

菜鸟学习vue3笔记-vue hooks初体验

import { ref } from "vue"; export default function () {let a1 ref(1);let a2 ref(5);let c ref(0);function add() {a1.value;a2.value;}return {add,a1,a2,c,}; }<template><div><p>第一个数字{{ a1 }}</p><p>第二个数字{{ a2…

java勤工助学信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web勤工助学信息管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为M…

Java线上问题排查思路

1、Java 服务常见问题 Java 服务的线上问题从系统表象来看大致可分成两大类: 系统环境异常、业务服务异常。 系统环境异常&#xff1a;主要从CPU、内存、磁盘、网络四个方面考虑。比如&#xff1a;CPU 占用率过高、CPU 上下文切换频率次数较高、系统可用内存长期处于较低值、…

K8s实战-基于LivenessProbe健康检查

LivenessProbe探针用于判断容器是否存活&#xff0c;如果探测到容器不健康&#xff0c;则kubelet将杀掉该容器&#xff0c;然后根据重启策略处理。 LivenessProbe的实现方式&#xff1a; ExecAction&#xff1a;在容器内部执行一个命令&#xff0c;如果该命令的返回码为0&…

计算机毕业设计 基于SpringBoot的高校危化试剂仓储管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

最短路径(数据结构实训)(难度系数100)

最短路径 描述&#xff1a; 已知一个城市的交通路线&#xff0c;经常要求从某一点出发到各地方的最短路径。例如有如下交通图&#xff1a; 则从A出发到各点的最短路径分别为&#xff1a; B&#xff1a;0 C&#xff1a;10 D&#xff1a;50 E&#xff1a;30 F&#xff1a;60 输…

白话机器学习的数学-1-回归

1、设置问题 投入的广告费越多&#xff0c;广告的点击量就越高&#xff0c;进而带来访问数的增加。 2、定义模型 定义一个函数&#xff1a;一次函数 y ax b &#xff08;a 是斜率、b 是截距&#xff09; 定义函数&#xff1a; 3、最小二乘法 例子&#xff1a; 用随便确定的参…

BDTC2023:CloudberryDB开源创新与实践

中国大数据技术大会&#xff08;BDTC&#xff09;由中国计算机学会&#xff08;CCF&#xff09;创立于2008年&#xff0c;已经成为国内外极具行业实践的专业大数据交流平台。12月22日-24日&#xff0c;第十七届中国大数据技术大会&#xff08;BDTC 2023&#xff09;在广州举行。…

文字识别技术在未来会有怎样的发展?

随着科技的不断发展&#xff0c;文字识别技术也在不断地改进和完善。未来&#xff0c;文字识别技术将会在更多的领域得到应用&#xff0c;并且将会更加智能化、高效化和个性化。 首先&#xff0c;随着深度学习技术的不断发展&#xff0c;文字识别技术将会更加智能化。目前&…

ubuntu22下安装minconda

bing 搜索 canda install 找到官方网站 https://docs.conda.io/projects/miniconda/en/latest/ 这里我们安装minconda。 官网有安装方法。 mkdir -p ~/miniconda3 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh…

docker的基本管理和相关概念

docker的基本管理和概念 docker&#xff1a;开源的应用容器引擎。基于go语言开发的。运行在linux系统当中的开源的&#xff0c;轻量级的“虚拟机” docker的容器技术可以在一台主机上轻松的为任何应用创建一个轻量级的&#xff0c;可移植的&#xff0c;自给自足的容器 docke…

Java 读取超大excel文件

注意&#xff1a;此参考解决方案只是针对xlsx格式的excel文件&#xff01; Maven <dependency><groupId>com.monitorjbl</groupId><artifactId>xlsx-streamer</artifactId><version>2.2.0</version> </dependency>读取方式1…

Android画布Canvas矩阵Matrix放大裁剪Rect区域的Bitmap,Kotlin

Android画布Canvas矩阵Matrix放大裁剪Rect区域的Bitmap&#xff0c;Kotlin private fun mydraw() {val originBmp BitmapFactory.decodeResource(resources, R.mipmap.pic).copy(Bitmap.Config.ARGB_8888, true)val newBmp Bitmap.createBitmap(originBmp.width, originBmp.h…

爬虫基础一(持续更新)

爬虫概念&#xff1a; 通过编写程序&#xff0c;模拟浏览器上网&#xff0c;然后让其去互联网上抓取数据的过程 分类&#xff1a; 1&#xff0c;通用爬虫&#xff1a;抓取一整张页面数据 2&#xff0c;聚焦爬虫&#xff1a;抓取页面中的局部内容 3&#xff0c;增量式爬虫&…

CUMT--Java--线程

目录 一、线程 1、概述 2、Java线程模型 3、主线程 二、创建线程 1、继承Thread类 2、实现Runnable接口 3、使用Callable和Future接口 三、线程生命周期 1、新建和就绪状态 2、运行和阻塞状态 3、死亡状态 四、线程优先级 五、线程同步 1、非同步情况 2、同步…

浅谈WPF之控件模板Control Template和数据模板Data Template

WPF不仅支持传统的Windows Forms编程的用户界面和用户体验设计&#xff0c;同时还推出了以模板为核心的新一代设计理念。在WPF中&#xff0c;通过引入模板&#xff0c;将数据和算法的“内容”和“形式”进行解耦。模板主要分为两大类&#xff1a;数据模板【Data Template】和控…

创建加密分区或者文件

文章目录 [GParted 中已清除的分区与未格式化的分区](https://superuser.com/questions/706624/cleared-vs-unformatted-partition-in-gparted)创建加密分区解密创建的加密分区以便挂载格式化设备未具体的格式&#xff08;这里为ext4格式&#xff09;创建挂载点目录挂载加密的文…

java在线票务系统(选座)Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java servlet 在线票务系统&#xff08;选座&#xff09;管理系统是一套完善的java web信息管理系统 系统采用serlvetdaobean&#xff08;mvc模式)&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要…

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第六节 理解垃圾回收GC,提搞程序性能

深入浅出图解C#堆与栈 C# Heaping VS Stacking 第六节 理解垃圾回收GC&#xff0c;提搞程序性能 [深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈](https://mp.csdn.net/mdeditor/101021023)[深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基…

泛目录是干什么用的蚂蚁seo泛程序

泛目录是干什么用的蚂蚁seo泛程序目录 泛目录是一种常见的网站优化方法&#xff0c;属于黑帽技术的一种。它的核心原理是利用高权重的网站继承目录&#xff0c;然后快速获得收录与排名。这种方法可以帮助网站在搜索引擎中获得更好的排名&#xff0c;从而吸引更多的流量。 泛目…