装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
装饰模式把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。
【继承+组合:装饰模式的Decorator类很重要,一方面继承自抽象类Component,另一方面在Decorator抽象类中组合Component对象,通过set方法将相应的Component对象赋值给Decorator中组合的Component对象,Decorator中的operation()操作继承自Component,并且它的方法体内容为:如果Decorator中组合的Component对象非空,执行该Component对象的operation()方法。各个具体的Decorator类中的operation()方法都会先调用父类的operation()方法,以使得Decorator中的operation()操作得以执行,达到层层包装的效果。参考代码理解 】
/**
* Component是定义一个对象接口,可以给这些对象动态地添加职责
*
* @author liu yuning
*
*/
public abstract class Component {
public abstract void operation();
}
/**
* ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责
*
* @author liu yuning
*
*/
public class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("具体对象的操作");
}
}
/**
* Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,
* 是无需知道Decorator的存在的
*
* @author liu yuning
*
*/
public abstract class Decorator extends Component {
protected Component component;
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
}
@Override
public void operation() {
if (component != null) {
component.operation();
}
}
}
class ConcreteDecoratorA extends Decorator {
private String addedState;
@Override
public void operation() {
// 首先运行原Component的operation(),再执行本类的功能,如addedState,相当于对原Component进行了装饰
super.operation();
addedState = "A中的new state ";
System.out.println(addedState + "具体装饰对象A的操作");
}
}
class ConcreteDecoratorB extends Decorator {
@Override
public void operation() {
super.operation();
addedBehavior();
System.out.println("具体装饰对象B的操作");
}
public void addedBehavior() {
System.out.print("B中的新增行为 ");
}
}
class ConcreteDecoratorC extends Decorator {
@Override
public void operation() {
super.operation();
System.out.println("C没有特殊行为 " + "具体装饰对象C的操作");
}
}
/**
* 装饰模式客户端调用代码,装饰的过程更像是层层包装,用前面的对象装饰后面的对象
*
* @author liu yuning
*
*/
public class DecoratorClient {
public static void main(String[] args) {
ConcreteComponent concreteComponent = new ConcreteComponent();
ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA();
ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB();
ConcreteDecoratorC concreteDecoratorC = new ConcreteDecoratorC();
concreteDecoratorA.setComponent(concreteComponent);
concreteDecoratorB.setComponent(concreteDecoratorA);
concreteDecoratorC.setComponent(concreteDecoratorB);
concreteDecoratorC.operation();
}
}
案例 穿衣服
/**
* 装饰模式(Decorator)
* Person类
*/
public class Person {
private String name;
public Person() {}
public Person(String name) {
this.name = name;
}
public void show() {
System.out.println("装扮的" + name);
}
}
/**
* 装饰模式(Decorator)
* 服饰类
*/
public class Finery extends Person {
protected Person component;
// 打扮
public void decorate(Person component) {
this.component = component;
}
@Override
public void show() {
if (component != null) {
component.show();
}
}
}
class TShirts extends Finery {
public void show() {
System.out.print("大T恤 ");
super.show();
}
}
class BigTrouser extends Finery {
public void show() {
System.out.print("大裤头 ");
super.show();
}
}
class Sneakers extends Finery {
public void show() {
System.out.print("破球鞋 ");
super.show();
}
}
class Suit extends Finery {
public void show() {
System.out.print("西装 ");
super.show();
}
}
class Tie extends Finery {
public void show() {
System.out.print("领带 ");
super.show();
}
}
class LeatherShoes extends Finery {
public void show() {
System.out.print("皮鞋 ");
super.show();
}
}
/**
* 装饰模式(Decorator)
* 客户端main方法
*/
public class Attire {
public static void main(String[] args) {
Person p0 = new Person("Kobe");
System.out.println("第一种装扮:");
TShirts tShirts = new TShirts();
BigTrouser bigTrouser = new BigTrouser();
Sneakers sneakers = new Sneakers();
tShirts.decorate(p0);
bigTrouser.decorate(tShirts);
sneakers.decorate(bigTrouser);
sneakers.show();
Person p1 = new Person("Allen");
System.out.println("第二种装扮:");
Suit suit = new Suit();
Tie tie = new Tie();
LeatherShoes leatherShoes = new LeatherShoes();
leatherShoes.decorate(p1);
tie.decorate(leatherShoes);
suit.decorate(tie);
suit.show();
}
}