当我们需要把所需的功能按正确的顺序串联起来进行控制,可以使用装饰者模式,它动态地给一个对象添加一些额外的职能,就添加功能来说,它比生成子类(例如之前利用继承实现计算器的例子)更加灵活
public abstract class Component {
public abstract void operation();
}
public class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("具体对象的操作");
}
}
public abstract class Decorator extends Component {
protected Component component;
public void setComponent(Component component) {
this.component = component;
}
//重写operation,实际上执行的是Component类的operation()方法
public void operation() {
if(component!=null) {
component.operation();
}
}
}
public class ConcreteDecoratorA extends Decorator {
private void AFunction() {
System.out.println("组合装饰A独有方法");
}
public void operation() {
//运行原Component的operation方法
super.operation();
//执行本类的功能,相当于对原Component方法进行了装饰
AFunction();
}
}
public class ConcreteDecoratorB extends Decorator {
private void BFunction() {
System.out.println("组合装饰B独有方法");
}
public void operation() {
//运行原Component的operation方法
super.operation();
//执行本类的功能,相当于对原Component方法进行了装饰
BFunction();
}
}
public class DemoDecorator {
public static void main(String[] args) {
ConcreteComponent cc=new ConcreteComponent();
ConcreteDecoratorA d1=new ConcreteDecoratorA();
ConcreteDecoratorB d2 = new ConcreteDecoratorB();
//用d1包装cc
d1.setComponent(cc);
d2.setComponent(d1);
d2.operation();
}
}
输出结果:
具体对象的操作
组合装饰A独有方法
组合装饰B独有方法
装饰模式是利用setComponent来对对象进行包装的,这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只需要关心自己的功能,不需要关心如何被添加到关系链中.
需求:写一个可以换各种各样的衣服裤子的个人形象系统
分析:人类是Component还是ConcreteComponent呢?对于设计模式的使用要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类.同样道理,如果只有一个ConcreteDecorator类,就没必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类.在这里我们就没有必要有Component类了,直接让服饰类Decorator继承人类Person(ConcreteComponent)就可以了
public class Person {
private String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
public void show() {
System.out.println("装扮的"+name);
}
}
public class Decorator extends Person {
protected Person person;
public void decorate(Person person) {
this.person=person;
}
public void show() {
if(person!=null) {
person.show();
}
}
}
public class TShirts extends Decorator {
public void show() {
System.out.println("T恤");
super.show();
}
}
public class Overcoat extends Decorator{
public void show() {
System.out.println("外套");
super.show();
}
}
public class Demo {
public static void main(String[] args) {
Person person=new Person("蒙蒙");
TShirts tShirts=new TShirts();
Overcoat overcoat=new Overcoat();
tShirts.decorate(person);
overcoat.decorate(tShirts);
overcoat.show();
}
}
总结:装饰模式是为已有功能添加更多功能的一种方式.当系统需要新功能的时候,是向旧的功能添加新的代码.这些新加的的代码通常装饰了原有类的核心职责和主要行为,问题来了,这样做在原有类中加入了新的字段,方法和逻辑,从而增加了原有类的复杂性,而这些新加入的东西仅仅是为了满足一些只在某些特定情况下才会执行的特殊行为的需要.而装饰模式提供了一个很好的解决方案,它把每个需要装饰的功能放在单独的类中,并让这个类包装它所装饰的对象,因此,当需要执行特殊行为时,测试代码就可以根据需要有选择的,按顺序地使用装饰功能包装对象
装饰模式的好处:
除去原类中的装饰功能,起到简化作用,有效地把原有类的核心职责和装饰功能区分开了,而且还可以去除相关类中重复的装饰逻辑
扩展:
当心,装饰模式的装饰顺序很重要,比如说先穿外套,再穿T恤是不行的.