裝飾模式
裝飾模式定義:動态地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比生成子類更為靈活。
結構圖:
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();
}
}
總結
使用原因: 當系統需要新功能的時候,是向舊的類中添加新的代碼。這些新加的代碼通常裝飾了原有類的核心職責或主要行為,在主類中加入了新的字段,新的方法,新的邏輯,進而增加了主類的複雜度。
裝飾模式提供了一個非常好的解決方案,它把每個要裝飾的功能放在單獨的類中,并讓這個類包裝它所要裝飾的對象,是以,當需要執行特殊行為時,客戶代碼就可以運作時根據需要有選擇的、按順序的使用裝飾功能包裝對象
優點:
把類中的裝飾功能從類中搬移去除,簡化原有類。把類的核心職責和裝飾功能區分開。