一、什么是装饰器模式:
当需要对类的功能进行拓展时,一般可以使用继承,但如果需要拓展的功能种类很繁多,那势必会生成很多子类,增加系统的复杂性,并且使用继承实现功能拓展时,我们必须能够预见这些拓展功能,也就是这些功能在编译时就需要确定了。那么有什么更好的方式实现功能的拓展吗?答案就是装饰器模式。
装饰器模式可以动态给对象添加一些额外的职责从而实现功能的拓展,在运行时选择不同的装饰器,从而实现不同的行为;比使用继承更加灵活,通过对不同的装饰类进行排列组合,创造出很多不同行为,得到功能更为强大的对象;符合“开闭原则”,被装饰类与装饰类独立变化,用户可以根据需要增加新的装饰类和被装饰类,在使用时再对其进行组合,原有代码无须改变。
但是装饰器模式也存在缺点,首先会产生很多的小对象,增加了系统的复杂性,第二是排错比较困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
二、UML结构图:
- Component:抽象构件,是定义一个对象接口,可以给这个对象动态地添加职责。
- ConcreteComponent:具体构件,是定义了一个具体的对象,也可以给这个对象添加一些职责。
Decorator:抽象装饰类,继承自 Component,从外类来扩展 Component 类的功能,但对于 - Component 来说,是无需知道 Decorator 存在的。
- ConcreteDecorator:具体装饰类,起到给 Component 添加职责的功能。
装饰者与被装饰者都拥有共同的超类,但这里继承的目的是继承类型,而不是行为。
三、代码实现:
今天周末,你不想在家做饭,于是出去外面吃饭,到了一个饭店,姚经理,查看菜单,点菜,上菜的过程才能吃到饭。
被装饰者:
//定义被装饰者
public interface Human {
void eat();
}
装饰者:
//定义装饰者
public abstract class Decorator implements Human
{
private Human human;
public Decorator(Human human)
{
this.human = human;
}
@Override
public void eat()
{
human.eat();
}
}
装饰内容:
//下面定义三种装饰,这是第一个,第二个第三个功能依次细化,即装饰者的功能越来越多
public class Decorator_zero extends Decorator {
public Decorator_zero(Human human) {
super(human);
}
public void goHotel() {
System.out.println("去饭店。。");
}
@Override
public void eat() {
super.eat();
goHotel();
}
}
public class Decorator_first extends Decorator {
public Decorator_first(Human human) {
super(human);
}
public void findMenu() {
System.out.println("找菜单。。");
}
@Override
public void eat() {
super.eat();
findMenu();
}
}
public class Decorator_two extends Decorator {
public Decorator_two(Human human) {
super(human);
}
public void eatFood() {
System.out.println("点菜吃饭。。");
}
@Override
public void eat() {
super.eat();
eatFood();
}
}
class Person implements Human {
@Override
public void wearClothes() {
System.out.println("穿什么呢。。");
}
}
测试:
public class DecoratorTest {
public static void main(String[] args)
{
Human person = new Person();
Decorator decorator = new Decorator_two(new Decorator_first(new Decorator_zero(person)));
decorator.eat();
}
}
结果: