1. 程式人生 > >裝飾模式的java實現例子

裝飾模式的java實現例子

說明:本文是《大話設計模式》一書的學習文摘和網上相關資訊文摘,原書程式碼例子用C#寫,下面用Java改寫。

1、裝飾模式:在不必改變原類檔案和使用繼承的情況下,動態地擴充套件一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。

2、裝飾模式由4種角色組成:
(1)抽象構件(Component)角色:給出一個抽象介面,以規範準備接收附加職責的物件。
(2)具體構件(Concrete Component)角色:定義一個將要接收附加職責的類。
(3)裝飾(Decorator)角色:持有一個構件(Component)物件的例項,並實現一個與抽象構件介面一致的介面,從外類來擴充套件Component類的功能,但對於Component類來說,是無需知道Decorato的存在的。
(4)具體裝飾(Concrete Decorator)角色:負責給構件物件新增上附加的職責。

3、裝飾模式的UML類圖



4、裝飾模式的特點
(1)裝飾物件和真實物件有相同的介面。這樣客戶端物件就能以和真實物件相同的方式和裝飾物件互動。
(2)裝飾物件包含一個真實物件的引用。
(3)裝飾物件接受所有來自客戶端的請求。它把這些請求轉發給真實的物件。
(4)裝飾物件可以在轉發這些請求以前或以後增加一些附加功能。這樣就確保了在執行時,不用修改給定物件的結構就可以在外部增加附加的功能。在面向物件的設計中,通常是通過繼承來實現對給定類的功能擴充套件。

5、適用性
(1)需要擴充套件一個類的功能,或給一個類新增附加職責。
(2)需要動態的給一個物件新增功能,這些功能可以再動態的撤銷。
(3)需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關係變的不現實。
(4)當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴充套件,為支援每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用於生成子類。

6、模式簡化
(1)如果只有一個Concrete Component類而沒有抽象的Component介面時,可以讓Decorator繼承Concrete Component。
(2)如果只有一個Concrete Decorator類時,可以將Decorator和Concrete Decorator合併。

7、程式碼實現

package demo4;
/**
 * 抽象構件角色
 */
public abstract class Component {
	public abstract void operation();
}


package demo4;
/**
 * 具體構件角色
 */
public class ConcreteComponent extends Component {		
	@Override
	public void operation() {
		System.out.println("具體物件的操作");
	}
}


package demo4;
/**
 * 裝飾角色
 */
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();
		}
	}
}


package demo4;
/**
 * 具體裝飾角色A
 */
public class ConcreteDecoratorA extends Decorator {
	//本類的獨有功能
	private String addedState;
	//首先執行原Component的operation(),再執行本類的功能,相當於對原Component進行了裝飾
	@Override
	public void operation(){
		super.operation();
		addedState = "New State";
		System.out.println("具體裝飾物件A的操作。" + addedState);
	}
}


package demo4;
/**
 * 具體裝飾角色B
 */
public class ConcreteDecoratorB extends Decorator {
	//首先執行原Component的operation(),再執行本類的功能,相當於對原Component進行了裝飾
	@Override
	public void operation() {
		super.operation();
		AddedBehavior();
		System.out.println("具體裝飾物件B的操作");
	}
	//本類的獨有功能
	private void AddedBehavior() {
		System.out.println("我是具體裝飾物件B的獨有方法");		
	}
}


package demo4;
/**
 * 客戶端程式碼
 */
public class Demo4 {

	public static void main(String[] args) {
		ConcreteComponent c = new ConcreteComponent();
		ConcreteDecoratorA d1 = new ConcreteDecoratorA();
		ConcreteDecoratorB d2 = new ConcreteDecoratorB();
		
		d1.setComponent(c);
		d2.setComponent(d1);
		d2.operation();
		/*執行輸出結果:
		具體物件的操作
		具體裝飾物件A的操作。New State
		我是具體裝飾物件B的獨有方法
		具體裝飾物件B的操作
		*/
	}
}

8、一個例子:給人搭配不同的服飾
package demo5;
/**
 *“Person”類(ConcreteComponent) 
 */
public class Person {

	public Person() {		
	}

	private String name;
	public Person(String name){
		this.name = name;
	}
	
	public void show(){
		System.out.println(String.format("裝扮的%s", name));
	}
}


package demo5;
/**
 * 服飾類(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();
		}
	}
}


package demo5;
/**
 * 具體服飾類(ConcreteDecorator)
 */
public class TShirts extends Finery {
	@Override
	public void show() {
		System.out.println("大T恤");
		super.show();
	}
}


package demo5;
/**
 * 具體服飾類(ConcreteDecorator)
 */
public class Sneakers extends Finery {
	@Override
	public void show() {
		System.out.println("球鞋");
		super.show();
	}
}


package demo5;
/**
 * 具體服飾類(ConcreteDecorator)
 */
public class BigTrouser extends Finery {
	@Override
	public void show() {
		System.out.println("垮褲");
		super.show();
	}
}


package demo5;
/**
 * 客戶端程式碼
 */
public class Demo5 {
	public static void main(String[] args) {
		Person xc = new Person("小菜");
			
		Sneakers pqx = new Sneakers();
		BigTrouser kk = new BigTrouser();
		TShirts dtx = new TShirts();
		
		pqx.decorate(xc);		
		kk.decorate(pqx);
		dtx.decorate(kk);
		dtx.show();
		/*
		執行結果:
		大T恤
		垮褲
		球鞋
		裝扮的小菜
		 */
	}
}