你或许不熟悉装饰器模式,但是漫威电影系列你肯定并不陌生,在电影播出之后,或许你听过这样的声音:
一个紫色番薯,打了一个响指,众多超级英雄消失一半。
可是番薯还是那个番薯,响指还是那个响指,是什么让这两个结合在一起拥有了强大的力量?答案就是:无限手套。电影很精彩,而与之巧合的是,手套的工艺和装饰器模式风格极为相似,所以今天就借来灭霸的手套,研究研究矮人族所制造的产品究竟有多么神奇。
装饰器模式的定义:
允许向一个现有的对象添加新的功能,同时又不改变其结构
🌰:手套每镶嵌一个宝石就增加一个超能力,而之前原本的能力更并不受影响,仍然可以使用。这就是手套无敌的秘密,也就是装饰器模式的魅力所在,让我们看一下用代码是如何实现的。
代码实现
装饰器模式,需要让所有使用的类都来自同一个接口,只有“同一类型”才能互相装饰
所以定义一个 Equipment 接口表示我们所有的装备,action 方法表示每个装备具有的功能
public interface Equipment {
void action();
}
我们定义两种场景: 徒手戴宝石、手套镶嵌宝石
- 徒手属于(天生自带)装备的一种,所以我们实现 Equipment 接口实现 action 方法
public class Hand implements Equipment {
@Override
public void action() {
System.out.println("手可以戴");
}
}
手套也是同理
public class Glove implements Equipment { @Override public void action() { System.out.println("手套可以镶嵌"); } }
接下来我们定义装饰类也就是 Diamond 宝石抽象类,因为宝石也是装备的一种,所以也需要实现 Equipment。 而我们的装饰有很多种宝石,所以定义装饰类用来实现多态从而装饰对象(手套、手)。
public abstract class Diamond implements Equipment{ Equipment equipment; public Diamond(Equipment equipment) { this.equipment = equipment; } @Override public void action() { equipment.action(); } }
构造器传入被装饰对象,这就是我们开头所提到的,所有使用的类都需要“同一类型”,这样才能将无论是原始对象,还是被装饰过的对象都能以 Equipment 类型传进去,从而再次装饰。
- 创建三个宝石,实现 Diamond 抽象类,从而具体化每个宝石的功能
public class RedDiamond extends Diamond {
public RedDiamond(Equipment equipment) {
super(equipment);
}
@Override
public void action() {
super.action();
System.out.println("红色现实宝石");
}
}
注意在宝石子类里面,每个 action 方法都额外执行了 super.action 方法,每个被装饰对象的 action 方法都会被执行。结合起来,整体功能是这样的👇
给手套镶嵌绿宝石,在这基础上再镶嵌红宝石。每次执行宝石本身功能之前都会先去执行super.action 直到执行了手套的功能后再返回执行宝石各自的功能,最终执行完所有功能。
以此类推,额外两个宝石类
public class GreenDiamond extends Diamond { public GreenDiamond(Equipment equipment) { super(equipment); } @Override public void action() { super.action(); System.out.println("绿色时间宝石"); } }
public class BlueDiamond extends Diamond { public BlueDiamond(Equipment equipment) { super(equipment); } @Override public void action() { super.action(); System.out.println("蓝色空间宝石"); } }
测试代码:
public class decoratorTest { public static void main(String[] args) { System.out.println("---------徒手----------"); Equipment hand = new Hand(); hand.action(); System.out.println(); Diamond redDiamond = new RedDiamond(hand);//用红宝石装饰手 redDiamond.action(); System.out.println(); Diamond greenAndRedDiamond = new GreenDiamond(redDiamond);//继续用绿宝石装饰 greenAndRedDiamond.action(); System.out.println("---------戴手套----------"); Equipment glove = new Glove(); glove.action(); System.out.println(); Diamond greenDiamond = new GreenDiamond(glove);//绿宝石装饰手套 greenDiamond.action(); System.out.println(); Diamond blueDiamond = new BlueDiamond(glove);//卸下绿宝石,镶嵌蓝宝石 blueDiamond.action(); } }
- 运行结果:
可以看出,每个装饰类可以装饰原本对象,也可以装饰被装饰过的对象,各个装饰类之间相互独立,实现各自功能。
我是 Haoo,一个乐观的码农,撰写有趣的文章。
如果这篇文章帮助到你,请收藏⭐点赞👍加关注👀,跟踪不迷路(🌻◡‿◡)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。