23種設計模式-----裝飾者設計模式學習詳解

一、裝飾者模式

1.概念定義

所謂裝飾者模式就是動態的給一個對象添加額外的功能,它比生成子類來得更加靈活。

2.應用場景

裝飾者模式多半應用於二次開發的過程中,當你需要對已有得系統添加新的功能,而又無法獲得源碼且不能使用繼承得情況下(要擴展得功能類裏邊含有final關鍵字),這時候就需要使用到裝飾者設計模式來解決問題。

其實即使我們有方法能夠獲取到源碼,基本上我們也不會去修改源碼,因爲修改源碼所引發得問題無異於一場災難,而且大大的違法了開放–封閉的設計原則(所謂開放封閉原則就是開放修改功能且封閉修改)。

使用裝飾者模式也要滿足一個前提:需要獲取到被裝飾類所實現的所有接口。

裝飾者模式舉例

需求:有一套無人車駕駛汽車的開發接口,裏面定義了啓動汽車、停止汽車的方法,然後Google公司實現了這個接口開發出了無人駕駛汽車,後來隨着時代的發展,這個接口的功能已經不能夠滿足我們的需求了,現Google公司需要在啓動汽車之前先自動查詢天氣預報以及車輛自身安全檢查的的情況,代碼如下:

接口Car

package com.gzgs.demo;

public interface Car {
	public void start();
	public void stop();
}

Google一代汽車

package com.gzgs.demo;

public class GoogleCar_1 implements Car {
	
	@Override
	public void start() {
		System.out.println("汽車啓動....");
	}
	
	@Override
	public void stop() {
		System.out.println("汽車停止....");
	}
}

Google二代汽車

package com.gzgs.demo;

public class GoogleCar_1 implements Car {
	
	@Override
	public void start() {
		System.out.println("汽車啓動....");
	}
	
	@Override
	public void stop() {
		System.out.println("汽車停止....");
	}
}

主類

package com.gzgs.demo;

public class demo {
	public static void main(String[] args) {
		GoogleCar_2 googleCar=new GoogleCar_2(new GoogleCar_1());
		googleCar.start();
		googleCar.stop();
	}
}

運行結果

在這裏插入圖片描述
通過這個案例應該可以很好的理解裝飾者模式,下面再深入瞭解一下這個模式。

裝飾者模式與繼承

why 裝飾者 no 繼承?

在上面這個例子中,其實要想實現這個新的功能用繼承的方式也能夠實現,繼承GoogleCar_1這個類之後直接重寫父類中的start()方法,可以輕而易舉的實現擴展功能,那爲什麼不使用繼承的方式呢? 其實在這個小例子中是可以使用繼承的,甚至會比用裝飾者模式來得方便,但是在實際的開發中,繼承就會顯得比較笨重,不夠靈活,使用裝飾者模式的話我們可以根據需要直接去調用被裝飾類中的原生方法,而使用繼承就得去重寫方法,這樣會顯得比較笨重。

裝飾者模式的本質實際上就是動態組合。

在面向對象的設計中,有一條基本的規則就是“儘量使用對象組合,而不是對象繼承”來擴展和複用功能。裝飾模式的思考起點就是這個規則

什麼是對象組合? 下面例子選自《研磨設計模式》一書的裝飾者模式章節

直接舉例來說吧,假若有一個對象 A,實現了一個 a1 的方法,而 C1 對象想要來擴展 A 的功能,給它增加一個 c11 的方法,那麼一個方案是繼承,

A 對象示例代碼如下:

public class A {
	public void a1(){
		System.out.println("now in A.a1");
	}
}

C1 對象示例代碼如下:


public class C1 extends A{
	public void c11(){
		System.out.println("now in C1.c11");
	}
}

另外一個方案就是使用對象組合,怎麼組合呢?就是在 C1 對象中不再繼承 A 對象了,而是去組合使用 A 對象的實例,通過轉調 A 對象的功能來實現 A 對象已有的功能。

寫個新的對象 C2 來示範,示例代碼如下:

public class C2 {
	/**
	* 創建A對象的實例
	*/
	private A a = new A();
	public void a1(){
		//轉調A對象的功能
		a.a1();
	}
	public void c11(){
		System.out.println("now in C2.c11");
	}
}

這樣相比可以看出對象組合會更加靈活且適用於實際的開發。

裝飾者模式的優缺點

比繼承更靈活

從爲對象添加功能的角度來看,裝飾模式比繼承更靈活。繼承是靜態的,而且一旦繼承所有子類都有一樣的功能。而裝飾模式採用把功能分離到每個裝飾器當中,然後通過對象組合的方式,在運行時動態地組合功能,每個被裝飾的對象最終有哪些功能,是由運行期動態組合的功能來決定的。

更容易複用功能

裝飾模式把一系列複雜的功能分散到每個裝飾器當中,一般一個裝飾器只實現一個功能,使實現裝飾器變得簡單,更重要的是這樣有利於裝飾器功能的複用,可以給一個對象增加多個同樣的裝飾器,也可以把一個裝飾器用來裝飾不同的對象,從而實現複用裝飾器的功能。

簡化高層定義

裝飾模式可以通過組合裝飾器的方式,爲對象增添任意多的功能。因此在進行高層定義的時候,不用把所有的功能都定義出來,而是定義最基本的就可以了,可以在需要使用的時候,組合相應的裝飾器來完成所需的功能。

裝飾模式的缺點是:會產生很多細粒度對象。

前面說了,裝飾模式是把一系列複雜的功能,分散到每個裝飾器當中,一般一個裝飾器只實現一個功能,這樣會產生很多細粒度的對象,而且功能越複雜,需要的細粒度對象越多。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章