装饰模式(Decorator) 动态地给一个对象添加一些额外的职责,就功能来说,装饰模式比生成子类更为灵活。
当某个对象需要动态添加一个或多个具有相同父类的不同子类时,若将这些子类直接关联至该对象,每当关联关系发生变化时,均需要修改该对象代码,耦合度较高,因此产生了装饰模式。通过装饰模式可以把类中的装饰功能搬移去除,简化原有的类,有效地把类的核心职责和装饰功能区分开来,去除了重复的装饰逻辑。
先看UML图:
其中Component类定义了一个抽象接口,可以通过ConcreteComponent来实例化它,也就是具体需要被装饰的对象,同时在实例化的过程中可动态地添加特定行为。如果只有一个ConcreteComponent类而没有抽象的Component类,那么ConcreteComponent在图中可替换Component的位置。
Decorator即为装饰类的父类,它继承了被装饰类,因此可以从外类来扩展Component类的功能,但对于Component来说,是无需知道装饰类的存在的,当需要添加新装饰时,继续在原有已装饰类上添加即可。这里也体现了继承中父类可被子类替代,并添加子类特征的特性。
举例
对于人这个对象来说,需要通过穿衣服来装饰,而我们每次穿衣服,都不应变更人的属性及操作,正适用于装饰模式,先定义人:
public class Person {
private String name;
public Person(){}
public Person(String name) {
this.name = name;
}
public void showClothes(){
System.out.println("打扮的" + name);
}
}
定义父类衣服,它继承了Person,便于从外部对Person进行装饰:
public class Clothes extends Person{
private Person person;
public void setPerson(Person person) {
this.person = person;
}
@Override
public void showClothes() {
if (person != null) {
person.showClothes();
}
}
}
定义具体的装饰类,包括西装、领带、T恤,球鞋等:
public class Suit extends Clothes {
@Override
public void showClothes() {
System.out.println("西装");
super.showClothes();
}
}
public class Tie extends Clothes {
@Override
public void showClothes() {
System.out.println("领带");
super.showClothes();
}
}
public class TShirts extends Clothes {
@Override
public void showClothes() {
System.out.println("T恤");
super.showClothes();
}
}
public class Sneakers extends Clothes {
@Override
public void showClothes() {
System.out.println("球鞋");
super.showClothes();
}
}
调用
public static void main(String[] args){
Person person = new Person("pzx");
Suit suit = new Suit();
Sneakers sneakers = new Sneakers();
Tie tie = new Tie();
TShirts tShirts = new TShirts();
suit.setPerson(person);
sneakers.setPerson(suit); //在已装饰了suit的person上继续添加其他装饰
tie.setPerson(sneakers);
tShirts.setPerson(tie);
tShirts.showClothes();
}
控制台输出
T恤
领带
破球鞋
西装
打扮的pzx