一.前言
装饰模式(Decorate)也叫包装模式(Wrapper)
装饰模式降低系统的耦合度,可以动态的增加或删除对象的责任,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类,创造出不同行为的组合,得到功能更加强大的对象。在Mybatis中Cache和CachingExecutor接口的实现类也使用了装饰者计模式。
但是也有缺点:产生很多小对象占据内存,影响性能容易出错,调试麻烦。
二.介绍
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
注意事项:可代替继承。
三.实例分析
人类都有吃的行为,吃不同的食物可能让你有不同的感觉.在本例中,我们模拟吃不同的食物让其产生不同的效果.同时也可多种食物叠加.让其产生多种效果
1.定义一个Human接口,
定义Human人类接口,它具有吃的行为功能
public interface Human {
void eat();//吃的功能
}
2.定义被装饰者,黄种人YellowPeople
定义一个具体的人种,黄种人YellowPeople 类
public class YellowPeople implements Human {
@Override
public void eat() {
System.out.println("我需要吃东西才有能量...");
}
}
3.定义装饰者的抽象父类
抽象父类有一个构造函数,构造函数里面的参数是抽象的人类,这也是能够实现装饰功能的一个必不可少的步骤。
public abstract class AbstractFood implements Human {
private Human human;
public AbstractFood(Human human) {
this.human = human;
}
@Override
public void eat() {
human.eat();
}
}
4.定义具体的装饰物
肉
public class Meat extends AbstractFood {
public Meat(Human human) {
super(human);
}
@Override
public void eat() {
super.eat();
show();
}
public void show() {
System.out.println("这是一碗肉,吃下去,有力气去搬砖了");
}
}
面
public class Noodles extends AbstractFood {
public Noodles(Human human) {
super(human);
}
@Override
public void eat() {
super.eat();
show();
}
public void show() {
System.out.println("这是一碗面,吃完可以好好睡一觉了");
}
}
大米
public class Rice extends AbstractFood {
public Rice(Human human) {
super(human);
}
@Override
public void eat() {
super.eat();
show();
}
public void show() {
System.out.println("这是大米,吃下去可以去敲代码了");
}
}
5.测试类
public class Test {
public static void main(String[] args) {
//创建被装饰者
YellowPeople yellowPeople = new YellowPeople() ;
//黄种人被装饰了附加了食物肉 ,具有搬砖的能力
Meat meat = new Meat( yellowPeople ) ;
//有肉吃的人被装饰了附加了大米 ,具有敲代码的动力
Rice rice = new Rice( meat ) ;
//有大米吃的人被装饰了附加了面条 ,可以美美的睡觉...
Noodles noodles = new Noodles( rice ) ;
noodles.eat();
}
}
运行结果:
我需要吃东西才有能量…
这是一碗肉,吃下去,有力气去搬砖了
这是大米,吃下去可以去敲代码了
这是一碗面,吃完可以好好睡一觉了