1. 程式人生 > >"圍觀"設計模式(13)--結構型之裝飾模式(Decorator Pattern)

"圍觀"設計模式(13)--結構型之裝飾模式(Decorator Pattern)

修飾模式,是面向物件程式設計領域中,一種動態地往一個類中新增新的行為的設計模式。就功能而言,修飾模式相比生成子類更為靈活,這樣可以給某個物件而不是整個類新增一些功能。----WIKIPEDIA

個人理解

相比而言我對裝飾模式的理解還不是很深入,在專案中還不知道該怎麼去使用它,或許是沒有遇到需要裝飾模式的情景吧,我對於裝飾模式的理解是通過裝飾模式可以實現對功能的擴充,由此我想到了面向切面程式設計,因為我記得AOP在實現的時候,就是對類的功能進行增強,可以在方法呼叫前執行、呼叫後、異常時等發生的時候去執行相應的處理,我在想會不會實現的時候採用的模式就是裝飾模式呢?這裡我先留著這個疑問後期有時間看原始碼的話再去探討到底是不是用了這個模式。裝飾模式中可以通過建構函式傳入要裝飾的類的例項,裝飾類和被裝飾的類要有相同的介面,保證當裝飾類沒有進行增強處理的時候,依然可以去執行被裝飾類應該執行的方法。

例項演示

假設有這樣的一個業務需要處理,比如儲存資料到資料庫中去,那麼我想對這個資料庫操作加事務機制,防止多個事務中某個事務失敗而其他的事務成功造成資料不完整的問題。拿使用者當做例子,假設使用者資訊除了包括基本的文字資訊之外還要有多個頭像,這樣的話,需要保證使用者基本資訊儲存也要保證頭像的資訊也儲存了,那麼需要對這兩個儲存的操作增加事務的裝飾。

這樣設計,你會發現這樣的話,在UserDaoDecorator類和Dao會直接耦合,不是很好,我們在Decorator類之上再抽象出一個抽象類,讓抽象類實現Dao並建立用於接收UserDao的例項,避免UserDaoDecorator直接與其他類耦合。

在UserDaoDecoratorParent抽象類中構造方法可以強制其子類實現帶引數的構造方法。

主要的類如下(全部程式碼下載地址:設計模式程式碼下載地址):

public interface Dao {

	public void saveUser(String user);
	
	public void saveHeadImages(String[] images);
	
	public void saveAll(String user, String[] images);
}

public class UserDao implements Dao{

	@Override
	public void saveUser(String user) {
		System.out.println("儲存使用者基本資訊:" + user);
	}

	@Override
	public void saveHeadImages(String[] images) {
		String imageInfo = "";
		int index = 1;
		for (String image : images) {
			if(index == 1){
				imageInfo += "index:"+ index + ""+ image;
			}else{
				imageInfo += "——index:"+ index + ""+ image;
			}
			index ++;
		}
		// ----->上面步驟列印輔助操作
		System.out.println("儲存使用者頭像:" + imageInfo);
	}

	@Override
	public void saveAll(String user, String[] images) {
		this.saveUser(user);
		this.saveHeadImages(images);
	}

	
}
裝飾類的抽象類,實現了Dao介面,保證其子類和UserDao擁有同樣的介面。
public abstract class UserDaoDecoratorParent implements Dao {

	protected Dao userDao;

	public UserDaoDecoratorParent(Dao userDao) {
		super();
		this.userDao = userDao;
	}
	
	public abstract void startTranscation();
	
	public abstract void stopTranscation();
	
}

裝飾類的具體實現
public class UserDaoDecorator extends UserDaoDecoratorParent {

	public UserDaoDecorator(Dao userDao) {
		super(userDao);
	}

	@Override
	public void saveUser(String user) {
		userDao.saveUser(user);
	}

	@Override
	public void saveHeadImages(String[] images) {
		userDao.saveHeadImages(images);
	}

	@Override
	public void saveAll(String user, String[] images) {
		// 開啟事務
		this.startTranscation();
		
		this.saveUser(user);
		this.saveHeadImages(images);
		
		// 結束事務
		this.stopTranscation();
	}

	@Override
	public void startTranscation() {
		System.out.println("開啟事務..");
	}

	@Override
	public void stopTranscation() {
		System.out.println("關閉事務..");
	}

	
}

裝飾模式的優點

1.  裝飾類和被裝飾類可以獨立發展而不會相互耦合,就是說裝飾類不需要知道被裝飾類的存在,而Decorator也不用知道裝飾類的內部組成。

2.  裝飾模式動態的擴充套件一個裝飾類的功能。

裝飾模式的缺點

多層的裝飾比較複雜,儘量減少裝飾類的數量,降低複雜度。