装饰器模式到底是什么呢?
什么时候用它?装饰器模式是一种结构型设计模式,它通过动态地为对象添加额外的行为来扩展对象的功能。装饰器通过组合而不是继承,提供了更加灵活的扩展方法。
当你希望在运行时通过添加行为来构建对象时,请使用装饰模式。
UML图"点击这里查看图片"
装饰器类使用组合和继承,理解这点很重要。
在装饰器模式里,我们对组件和装饰器使用相同类型。装饰器通过组合组件对象来获取行为,即获取组件对象中的字段或方法。而装饰器继承组件(即扩展),使得装饰器对象可以当作组件对象使用。
装饰器模式实现了开闭原则,即对扩展开放,对修改关闭。添加组件或装饰器十分简单。例如,如果你想添加另一个具体的装饰器,你只需创建一个表示它的类,并继承装饰器类。
例子想象我们正在为一家冰淇淋店建立一个系统。这家店有各种口味的冰淇淋和 topping。系统需要显示每份冰淇淋的描述(包括顶部的配料)及其成本。
这是一张图片。
- 冰淇淋成分和配料都使用共同的 IceCream 接口,它们都被声明为 IceCream 对象。
- 每种具体的冰淇淋都重写了 cost 方法,因为每种冰淇淋的价格各不相同。
- Topping 类提供了具体配料的接口,并引用一个 IceCream 对象。
- 如果系统需要另一种配料,例如焦糖酱,你只需要创建一个继承自 Topping 类的 CaramelSource 类即可。
IceCream 类:
// 表示冰激凌的抽象类
public abstract class IceCream {
public String description = "未知的冰激凌";
public String getDescription() {
return description;
}
public abstract double price();
}
全屏 全屏退出
巧克力冰激凌类:
// 具体类
public class ChocolateIceCream extends IceCream {
public ChocolateIceCream() {
this.description = "巧克力冰淇淋";
}
@Override
public double cost() {
return 1.99;
}
}
点击全屏,点击退出全屏
最棒的课程:
// 基础装饰类
public abstract class Topping extends IceCream {
public IceCream iceCream;
// 所有子类(具体装饰类)需要实现 getDescription 方法,
// 通过将其声明为抽象方法,我们要求所有子类实现此方法
public abstract String getDescription();
}
切换到全屏 退出全屏
MapleNuts 类:
// 具体装饰类
public class MapleNuts extends Topping { // 继承自装饰层父类
public MapleNuts(IceCream iceCream) {
this.iceCream = iceCream;
}
@Override
public String getDescription() {
return iceCream.getDescription() + ", MapleNuts"; // 添加枫糖坚果
}
@Override
public double cost() {
return iceCream.cost() + .30; // 计算成本
}
}
全屏 退出全屏
PeanutButterShell 类:
// 具体的装饰类
public class PeanutButterShell extends Topping {
public PeanutButterShell(IceCream iceCream) {
this.iceCream = iceCream;
}
@Override
public String getDescription() {
return iceCream.getDescription() + ", 加上花生壳酱";
}
@Override
public double cost() {
return iceCream.cost() + .30; // 增加0.30元
}
}
全屏模式,退出全屏模式
客户端类(Client 类):
public class 客户 {
public static void main(String[] args) {
冰淇淋 iceCream = new 巧克力冰淇淋();
System.out.println("描述:" + iceCream.getDescription() + ",价格:" + iceCream.cost() + "元");
iceCream = new 枫糖坚果(iceCream);
System.out.println("描述:" + iceCream.getDescription() + ",价格:" + iceCream.cost() + "元");
iceCream = new 花生酱壳冰淇淋(iceCream);
System.out.println("描述:" + iceCream.getDescription() + ",价格:" + iceCream.cost() + "元");
}
}
点击全屏 点击退出全屏
输出:
巧克力冰激凌,1.99美元
加枫坚果的巧克力冰激凌,2.29美元
加枫坚果和花生壳的巧克力冰激凌,2.59美元
切换到全屏,切换回正常模式
……
这里可以查看所有设计模式的实现。
GitHub仓库链接
附注:
我是新手写技术博客,如果有任何关于写作的建议,或者有任何不明白的地方,请在下面评论!
谢谢大家的阅读 :)
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦