裝飾者模式

例子:一個可以給人搭配不同服飾的系統,即可以換各種各樣的衣服褲子的個人形象系統

最先想到的是,先建一個Person類

package deractor;

public class Person {
	private String name;
	public Person(String name){
		this.name=name;
	}
	public void show(){
		System.out.println("裝扮"+name);
	}
}

各種服飾的抽象類

package deractor;

abstract class Finery {
	public abstract void Show();
}

服飾子類

package deractor;

public class TShirts extends Finery{

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.println("大T恤");
	}

}
package deractor;

public class BigTrouser extends Finery{

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.println("垮褲");
	}

}
package deractor;

public class WearSneakers extends Finery{

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.println("破球鞋");
	}

}
package deractor;

public class WearSuit extends Finery{

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.println("西裝");
	}
	
}

測試代碼

package deractor;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Person test=new Person("Autumn");
		System.out.println("裝扮如下");
		Finery ts=new TShirts();
		Finery bt=new BigTrouser();
		Finery ws=new WearSneakers();
		Finery wsuit=new WearSuit();
		ts.Show();
		bt.Show();
		ws.Show();
		wsuit.Show();
	}

}

Test中,把“大T恤”、“垮褲”、“破球鞋”、“西裝”一個一個進行顯示,好比:你光着身子,當着大家的面,一件一件穿上衣服,so,應該在內部組裝完畢

即裝飾模式Decorator,動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比生成子類更爲靈活。


其中,Component定義一個對象接口,可以給這些對象動態地添加職責。ConcreteComponent定義了一個具體的對象,也可以給這個對象添加一些職責。Decorator裝飾抽象類,繼承了Component,從外類來擴展Component類的功能,但對於Component來說,無需知道Decorator的存在,至於ConcreteDecorator就是具體的裝飾對象,起到給Component添加職責的功能。基本代碼實現如下:

package deractor;

abstract class Component {
	public abstract void Operation();
}
package deractor;

public class ConcreteComponent extends Component{

	@Override
	public void Operation() {
		// TODO Auto-generated method stub
		System.out.println("具體的操作對象");
	}

}
package deractor;

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();
		}
	}
}

package deractor;

public class ConcreteDecoratorA extends Decorator{
	private String addedState;
	public void Operation(){
		super.Operation();//首先運行原Operation,再執行本類的功能,如addedState,相當於對原Component進行了裝飾
		addedState="new state";
		System.out.println("具體裝飾對象A的操作");
	}
}
package deractor;

public class ConcreteDecoratorB extends Decorator{
	public void Operation(){
		super.Operation();
		AddedBehavior();
		System.out.println("具體裝飾對象B的操作");
	}
	private void AddedBehavior(){
		
	}
}

裝飾的方法是:先用ConcreteComponent實例化對象c,然後用ConcreteDecoratorA的實例化對象d1來包裝c,再用ConcreteDecoratorB的對象d2包裝d1,最終執行d2的Operation

package deractor;

public class DeTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ConcreteComponent c=new ConcreteComponent();
		ConcreteDecoratorA d1=new ConcreteDecoratorA();
		ConcreteDecoratorB d2=new ConcreteDecoratorB();
		
		d1.setComponent(c);
		d2.setComponent(d1);
		d2.Operation();
	}

}

如果只有一個ConcreteComponent類而沒有抽象的Component類,那麼Decorator類可以是ConcreteComponent的一個子類,如果只有一個ConcreteDecorator類,那麼就沒有必要建立一個單獨的Decorator類,而是可以把Decorator和ConcreteDecorator的責任合併成一個類

將上述衣服搭配稍作修改

package deractor;

public class PersonConcreteComponent {
	private String name;
	public PersonConcreteComponent(){}
	public PersonConcreteComponent(String name){
		this.name=name;
	}
	public void Show(){
		System.out.println("裝扮的"+name);
	}
}
package deractor;

public class FineryDecorator extends PersonConcreteComponent{
	protected PersonConcreteComponent component;
	
	public void Decorate(PersonConcreteComponent component){
		this.component=component;
	}
	public void Show(){
		if(component!=null){
			component.Show();
		}
	}
}
package deractor;

public class TShirts2 extends FineryDecorator{

	@Override
	public void Show() {
		// TODO Auto-generated method stub	
		super.Show();
		System.out.println("大T恤");
	}

}
package deractor;

public class WearSneakers2 extends FineryDecorator{

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		super.Show();
		System.out.println("破球鞋");
	}

}
package deractor;

public class BigTrouser2 extends FineryDecorator{

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		super.Show();
		System.out.println("垮褲");
	}

}
package deractor;

public class DecorateTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		PersonConcreteComponent person=new PersonConcreteComponent("Autumn");
		System.out.println("the following裝扮");
		
		TShirts2 ts=new TShirts2();
		BigTrouser2 bt=new BigTrouser2();
		WearSneakers2 ws=new WearSneakers2();
		
		ts.Decorate(person);
		bt.Decorate(ts);
		ws.Decorate(bt);
        ws.Show();
	}

}

運行結果:

the following裝扮
裝扮的Autumn
大T恤
垮褲
破球鞋
由此可以看出,裝飾模式把每個要裝飾的功能放在單獨的類中,並讓這個類包裝它索要裝飾的對象,因此,當需要執行特殊行爲時,客戶代碼就可以在運行時根據需要有選擇地、按順序地使用裝飾功能包裝對象。

發佈了92 篇原創文章 · 獲贊 14 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章