Java设计模式 - 装饰者模式
:smile: 不断学习才是王道
:fire: 继续踏上学习之路,学之分享笔记
:facepunch: 总有一天我也能像各位大佬一样
:trophy:原创作品,更多关注我CSDN: 一个有梦有戏的人
:facepunch:准备将博客园、CSDN一起记录分享自己的学习心得!!!
:full_moon_with_face:分享学习心得,欢迎指正,大家一起学习成长!
目录
- Java设计模式 - 装饰者模式
简介
装饰者模式是一种结构型模型,是动态的给对象增加职责,对于新增功能来说要比通过子类方式更加的灵活。他允许对一个对象进行添加新的功能,但不能改变结构。
装饰者模式实例
德德奶茶店里有许多种奶茶,奶茶还能根据自己的喜欢添加额外的料。加入奶茶有很多种,料也有很多,要求既能够在扩展奶茶种类的时候,改动方便,不能改变结构。使用面向对象的方式计算不同种类奶茶的费用。用户可以只买不加料,也可以买奶茶再根据自己的喜好加料。
既想实现需求,又不能让类太繁重,又要做到高扩展,改动方便。于是就使用了装饰者模式,简单说一下如何使用装饰者首先需要一个抽象类,里面除了价格等属性,还需要有个能够让子类实现的抽象方法来计算费用。具体的奶茶再来继承这个抽象类,实现其方法并设置初始值。还需要定义总体装饰者,他是继承了抽象类,采用组合的方式,计算总价格,其他真正地装饰者也就是调料,他们再去继承这个总体装饰者。使用的使用只要实例化父类,对象为具体的奶茶类型,在加料的时候,只需要把这杯奶茶送到装饰者上,去让装饰者装饰,最后返回还是这个父类。
具体的类图如下
接下来一步一步编写代码来实现买一杯 红豆奶茶 + 牛奶 + 布丁
①、抽象类
定义饮料-抽象类,包含描述和费用两个属性,还有个抽象方法-计算价格,提供给子类去实现。
package com.lyd.demo.drink; /** * @Author: lyd * @Description: 饮料-抽象类 * @Date: 2022-08-29 */ public abstract class Drink { private String describe; // 描述 private float price = 0.0f; public String getDescribe() { return describe; } public void setDescribe(String describe) { this.describe = describe; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } // 计算费用 - 抽象 - 子类实现 public abstract float cost(); }
②、定义单体类
定义奶茶类,只需要继承饮料类,并且获取父类的价格。
package com.lyd.demo.drink; /** * @Author: lyd * @Description: 奶茶类 * @Date: 2022-08-29 */ public class MilkTea extends Drink { @Override public float cost() { return super.getPrice(); } }
③、定义具体奶茶
红豆奶茶和珍珠奶茶的代码相似,这里只粘贴红豆奶代码。具体奶茶,要设置描述和单价。
package com.lyd.demo.drink; /** * @Author: lyd * @Description: 红豆奶茶 * @Date: 2022-08-29 */ public class RedBeanMilkTea extends MilkTea { public RedBeanMilkTea() { setDescribe(" 红豆奶茶 "); setPrice(7.0f); } }
④、定义装饰类
总体装饰者,继承饮料类
package com.lyd.demo.decorator; import com.lyd.demo.drink.Drink; /** * @Author: lyd * @Description: 装饰者 * @Date: 2022-08-29 */ public class Decorator extends Drink { Drink drink; public Decorator(Drink drink) { // 组合 this.drink = drink; } @Override public float cost() { // 计算价格综合 return super.getPrice() + drink.cost(); } @Override public String getDescribe() { return drink.getDescribe() + " + " + super.getDescribe() + " " + super.getPrice(); } }
⑤、定义具体装饰者
具体装饰者就是要添加的料,这里只粘贴单个代码示例,其他相似。
package com.lyd.demo.decorator; import com.lyd.demo.drink.Drink; /** * @Author: lyd * @Description: 装饰器 - 牛奶 * @Date: 2022-08-29 */ public class Milk extends Decorator { public Milk(Drink drink) { super(drink); setDescribe(" 牛奶 "); setPrice(3.0f); } }
⑥、测试实例
买一杯 红豆奶茶 + 牛奶 + 布丁。
通过父类实例化具体的奶茶子类,调用其计算总价方法;要是需要加料,只要把奶茶实例放到new调料实例中,让装饰者去装饰这个类,最后返回也是饮料类。通过层层套入装饰的方式就实现了装饰者模式。在此,如果是买第二杯奶茶,只需要在new一个对应奶茶的实例。如果还有额外的品种奶茶需要添加,只要继续添加xx奶茶类,不会改变结构,或者是需要添加调料,也是如此操作,让其多个具体的装饰者。
package com.lyd.demo.test; import com.lyd.demo.decorator.Milk; import com.lyd.demo.decorator.Pudding; import com.lyd.demo.drink.Drink; import com.lyd.demo.drink.PearlMilkTea; /** * @Author: lyd * @Description: 测试类 * @Date: 2022-08-29 */ public class DecorateTest { public static void main(String[] args) { // 买一杯 红豆奶茶 + 牛奶 + 布丁 // 实例化为父类对象,红豆奶茶 Drink pearlMilkTea = new PearlMilkTea(); // 先观察红豆奶茶的输出 System.out.println("您购买了: " + pearlMilkTea.getDescribe()); System.out.println("您购买的费用: " + pearlMilkTea.cost()); // 添加牛奶之后 System.out.println("添加牛奶之后"); pearlMilkTea = new Milk(pearlMilkTea); System.out.println("您购买了: " + pearlMilkTea.getDescribe()); System.out.println("您购买的费用: " + pearlMilkTea.cost()); // 再添加布丁之后 System.out.println("再添加布丁之后"); pearlMilkTea = new Pudding(pearlMilkTea); System.out.println("您购买了: " + pearlMilkTea.getDescribe()); System.out.println("您购买的费用: " + pearlMilkTea.cost()); } }
运行结果: