众所周知,面向对象设计有一个很重要的原则是对修改关闭,对扩展开放。在业务需求需要扩展时,我们常常使用继承的方式,让子类替代整个父类,但是这样会导致代码量急速增加。因此可以使用封装器,也就是装饰模式,简单来说,可以在不更改一个对象的情况下,动态的为这个对象添加一些行为。
买东西流程图
假设你平时出门逛街只买一杯奶茶就回家了,但是今天你想先买鸡蛋,然后再买橘子,最后买完奶茶再回家,流程如下图,我们并没有改变"买奶茶"这个行为,只不过在它之前添加了两个行为而已。
代码设计思路
- 首先我们要定义一个接口
ComponentInteface
,这个接口中有个抽象方法用来定义行为,就叫buy方法吧 - 其次,由于我们雷打不动,每次出门都会买奶茶,因此要定义一个买奶茶的类,实现
ComponentInteface
接口中的买东西方法,具体实现就是输出一句话:"我要买奶茶" - 现在需求来了,我们除了买奶茶,还要买鸡蛋和橘子,也就是对之前的行为进行
装饰
,因此我们需要定义一个装饰基类
并实现ComponentInteface
接口,这个类中保存着指向ComponentInteface
实现类对象的引用 - 最后,我们定义买鸡蛋和买橘子的类,并继承装饰基类,由于装饰基类是接口
ComponentInteface
的实现类,因此,继承了装饰基类的所有子类也都是ComponentInteface
的隐式实现类。
代码实现
顶级接口
java
public interface ComponentInteface {
void buy();
}
买奶茶
java
public class BuyMilkTea implements ComponentInteface{
@Override
public void buy() {
System.out.println("我要买奶茶");
}
}
装饰器基类
java
public class BaseDecorator implements ComponentInteface{
private ComponentInteface component;
public void setComponent(ComponentInteface component) {
this.component = component;
}
@Override
public void buy() {
component.buy();
}
}
买鸡蛋
java
public class BuyEggDecorator extends BaseDecorator {
@Override
public void buy() {
System.out.println("我要买鸡蛋");
super.buy();
}
}
买橘子
java
public class BuyOrangeDecorator extends BaseDecorator {
@Override
public void buy() {
System.out.println("我要买橘子");
super.buy();
}
}
测试
java
public class main {
public static void main(String[] args) {
BaseDecorator baseDecorator = new BaseDecorator();
BuyEggDecorator buyEggDecorator = new BuyEggDecorator();
BuyOrangeDecorator buyOrangeDecorator = new BuyOrangeDecorator();
BuyMilkTea buyMilkTea = new BuyMilkTea();
baseDecorator.setComponent(buyEggDecorator);
buyEggDecorator.setComponent(buyOrangeDecorator);
buyOrangeDecorator.setComponent(buyMilkTea);
baseDecorator.buy();
}
}
输出结果