装饰模式
装饰模式定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
结构图:
Component:定义对象接口,可以给对象动态地添加职责。
ConcreteComponent:定义具体的对象,即装饰的对象,也可以给该对象添加职责。
Decorator:装饰抽象类,继承了Component,从外类来扩展Component类的功能。(Component不知道Decorator的存在)
代码实现
Component类:
/**
* Component
* @author xukai
* 2016年3月8日 上午10:09:38
*/
public abstract class Component {
public abstract void operation();
}
ConcreteComponent类:
/**
* ConcreteComponent
* @author xukai
* 2016年3月8日 上午10:10:57
*/
public class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("装饰对象的操作");
}
}
Decorator类:
/**
* 装饰父类
*
* @author xukai 2016年3月8日 上午10:11:32
*/
public abstract class Decorator extends Component {
protected Component component;
public void setComponent(Component component) {
this.component = component;
}
@Override
public void operation() {
if (component != null) {
component.operation();
}
}
}
ConcreteDecoratorA类:
/**
* 具体服装类
* @author xukai
* 2016年3月8日 上午10:13:55
*/
public class ConcreteDecoratorA extends Decorator {
/**
* 本类独有功能,区别其他具体服饰类
*/
@SuppressWarnings("unused")
private String addedState;
/**
* 1.运行原Component的operation方法
* 2.执行本类方法,addedState,对其进行装饰
*/
@Override
public void operation() {
super.operation();
addedState = "New State";
System.out.println("装饰A");
}
}
ConcreteDecoratorB类:
/**
* 具体服饰类
*
* @author xukai 2016年3月8日 上午10:15:57
*/
public class ConcreteDecoratorB extends Decorator {
/**
* 本类特有方法,区别其他具体服饰类
*/
private void addedBehavior(){
System.out.println("装饰B");
}
/**
* 1.运行原Component的operation方法
* 2.执行本类方法,addedBehavior,对其进行装饰
*/
@Override
public void operation() {
super.operation();
addedBehavior();
}
}
客户端:
/**
* 客户端测试
* @author xukai
* 2016年3月8日 上午10:20:56
*/
public class DecoreteClient {
public static void main(String[] args) {
ConcreteComponent concrete = new ConcreteComponent(); //1
ConcreteDecoratorA concrete_A = new ConcreteDecoratorA(); //2
ConcreteDecoratorB concrete_B = new ConcreteDecoratorB(); //3
concrete_A.setComponent(concrete); //4
concrete_B.setComponent(concrete_A); //5
concrete_B.operation(); //6
}
}
流程分析:
1.创建ConcreteComponent对象——concrete
2.创建ConcreteDecoratorA对象——concrete_A
3.创建ConcreteDecoratorB对象——concrete_B
4.将concrete_A中的protected的Component设置为concrete(ConcreteComponent对象)
5.将concrete_B中的protected的Component设置为concrete_A(ConcreteDecoratorA对象)
6.1执行ConcreteDecoratorB中的operation()方法
6.2执行super.operation(),实际为其父类Decorator的operation方法
6.3Decorator的operation方法内容为,执行Component的operation方法,此时Component实际为ConcreteDecoratorA对象
6.4执行ConcreteDecoratorA的operation方法:super.operation,继续执行Decorator的operation方法,此时Component实际为ConcreteComponent对象
6.5执行ConcreteComponent中的operation方法
6.6执行ConcreteDecoratorA特有的装饰
6.7执行ConcreteDecoratorB特有的装饰
下面是一个demo
问题:要求写一个可以给人搭配不同的服饰的系统。
*注:
如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。
如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。
Person类:
public class Person {
public Person() {
}
public Person(String name) {
this.name = name;
}
private String name;
public void show(){
System.out.println(name + "穿衣顺序:");
}
}
服饰类(Decorator)
/**
* 服饰类
* @author hcc
*
*/
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();
}
}
}
具体服饰类(ConcreteDecorator)
/**
* 具体服饰类:T恤
* @author hcc
*
*/
public class TShirts extends Finery {
@Override
public void show() {
super.show();
System.out.println("T恤");
}
}
具体服饰类(ConcreteDecorator)
/**
* 具体服饰类:垮裤
* @author hcc
*
*/
public class BigTrouser extends Finery {
@Override
public void show() {
super.show();
System.out.println("垮裤");
}
}
测试类:
public class DecorateDemoTest {
public static void main(String[] args) {
Person person = new Person("徐凯");
TShirts tShrits = new TShirts();
BigTrouser bigTrouser = new BigTrouser();
tShrits.decorate(person);
bigTrouser.decorate(tShrits);
bigTrouser.show();
}
}
总结
使用原因:
当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,在主类中加入了新的字段,新的方法,新的逻辑,从而增加了主类的复杂度。
装饰模式提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以运行时根据需要有选择的、按顺序的使用装饰功能包装对象
优点:
把类中的装饰功能从类中搬移去除,简化原有类。把类的核心职责和装饰功能区分开。