1. 程式人生 > >Java裝飾器模式(Decorator)

Java裝飾器模式(Decorator)

一、概述
      裝飾模式又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴充套件物件的功能,可以在不建立更多子類的情況下,將物件的功能加以擴充套件,是繼承關係的一個替代方案。用意:動態地為物件新增一些額外的功能,就好比為房子進行裝修一樣。
      特點:1)裝飾者和被裝飾者擁有相同的超型別(可能是抽象類也可能是介面);2)在裝飾類中包含一個被裝飾元件類的物件引用;3)可以為被裝飾物件新增額外的功能;4)在裝飾類中重寫被裝飾元件類中的方法,並對被裝飾元件類中對應的方法呼叫;5)因為裝飾者和被裝飾者擁有相同的抽象型別,因此在任何需要原始物件(被包裝)的場合,都可以用裝飾過的物件來替代它;可以用多個裝飾類來包裝一個物件,裝飾類可以包裝裝飾類或被裝飾物件。簡而言之
,裝飾模式保持介面,增強效能;繼承至Component同時包含一個Component作為其成員變數(裝飾器模式動機中的動態地增加功能是在這裡實現的)。
二、結構圖及其角色
      抽象構件(Component)角色:給出一個抽象介面,裝飾器模式中公共方法的類,在裝飾器模式結構圖的頂層,以規範準備接收附加責任的物件;
具體構件(ConcreteComponent)角色:是要動態擴充套件的物件,轉換器模式中具體的被裝飾的類,它繼承自Component;
裝飾(Decorator)角色:持有一個構件(Component)物件的例項,它是裝飾器模式中的核心物件,所有具體裝飾器物件的父類,完成裝飾器的部分職能。可以只對被裝飾的物件進行一些簡單的包裹,也可包含對Component中方法的實現;

具體裝飾(ConcreteDecorator)角色:完成具體的裝飾功能。裝飾功能的實現是通過呼叫被裝飾物件對應的方法,加上裝飾物件自身的方法。這是裝飾器模式動機中的新增額外功能的關鍵。

      具體事例:MM們要過生日了,最起碼先送個蛋糕。蛋糕種類很多,如巧克力、冰淇淋、奶油等等,這都是基本的了,再加點額外的裝飾,如蛋糕裡放點花、放點乾果吃著更香等等。看看我是如何設計的。我想既然是蛋糕,那我就把蛋糕作為一個抽象類,剩下的蛋糕子型別來繼承它,每個子類都有吃該蛋糕的感覺,看起來真的不錯。蛋糕的子類分別是乳酪蛋糕、冰淇淋蛋糕、放賀卡的冰淇淋蛋糕。但是某次某個MM的生日蛋糕喜歡要的蛋糕我這都沒有,比如帶鮮花的巧克力蛋糕、帶果仁的牛奶蛋糕等等。那我還要繼續新增蛋糕的子類,問題出現了,這樣會造成大量的蛋糕子類,真是噩夢啊。那麼我要好好思考這個問題了,發現了剛才的設計確實有問題,發現了真正的要關注的主體是蛋糕,而賀卡、花、果仁等等只不過是裝飾的作用。思路來了:蛋糕作為主體,其他的東西都加到蛋糕上。MM要啥我就加啥唄。到現在我們要明確的是:蛋糕是主體;花、賀卡、果仁等等是裝飾者;可以用裝飾者包裝蛋糕。這個實力的結構圖如下所示


三、示例程式
public abstract class Cake {
	// Cake是個抽象類,扮演的是抽象構件(Component)角色,它已經實現了
	// getRemark的方法,但沒有實現getImpression,必須被子類實現。
	String remark = "蛋糕";

	public String getRemark() {
		return remark;
	}

	// 用來描述吃蛋糕的感覺
	public abstract String getImpression();
}
public abstract class Decorator extends Cake {
	Cake cake;

	// 引用一個Cake,讓被裝飾者進入裝飾者之中;
	// 這裡用的是構造方法注入,這樣就可以呼叫Cake例項的方法了。
	public Decorator(Cake cake) {
		this.cake = cake;
	}

	// 讓裝飾器的子類都去實現getRemark方法,業務需要每個裝飾器都要有描述。
	public abstract String getRemark();
}
public class CheeseCake extends Cake {

	// 乳酪蛋糕的構造方法,修改乳酪蛋糕的描述。
	public CheeseCake() {
		super.remark = "乳酪蛋糕";
	}

	// 實現了Cake抽象類的getImpression吃乳酪蛋糕的感覺。。
	public String getImpression() {
		return "乳酪蛋糕,香甜感受";
	}
}
public class IceCake extends Cake {

	// 冰淇淋蛋糕的構造方法,修改冰淇淋蛋糕的描述。
	public IceCake() {
		super.remark = "冰淇淋蛋糕";
	}

	// 實現了Cake抽象類的getImpression吃冰淇淋蛋糕的感覺。。
	public String getImpression() {
		return "冰涼的感受很好";
	}
}
public class FlowerDecorator extends Decorator {

	// 傳入一個cake例項,也就是前面所實現的Cake的子類,如乳酪蛋糕,巧克力蛋糕等等。
	public FlowerDecorator(Cake cake) {
		// 呼叫父類的構造方法,可以獲取Cake的例項了。就可以呼叫Cake例項的方法
		super(cake);
		super.remark = "一朵玫瑰花";
	}

	@Override
	public String getRemark() {
		return cake.getRemark() + "+" + super.remark;
	}

	// 實現了裝飾器抽象類的getImpression方法。
	// 這是重點。我們通過構造方法傳入的cake例項。對cake進行了裝飾,增加了新的功能。
	@Override
	public String getImpression() {
		return super.cake.getImpression() + "," + "看到一朵花真是happy";
	}
}
public class NutsDecorator extends Decorator {

	// 傳入一個cake例項,也就是前面所實現的Cake的子類
	public NutsDecorator(Cake cake) {
		// 呼叫父類的構造方法,可以獲取Cake的例項了。就可以呼叫Cake例項的方法
		super(cake);
		super.remark = "一顆果仁";
	}

	@Override
	public String getRemark() {
		return cake.getRemark() + "+" + super.remark;
	}

	// 實現了裝飾器抽象類的getImpression方法。
	// 這是重點。我們通過構造方法傳入的cake例項,對cake進行了裝飾,增加了新的功能。
	@Override
	public String getImpression() {
		return super.cake.getImpression() + "," + "看到一顆果仁,哈哈";
	}
}
public class Client {
	public static void main(String[] args) {
		// 用果仁,花包裝乳酪蛋糕。
		Cake nutsFlowerChocolateCake = new NutsDecorator(new FlowerDecorator(
				new CheeseCake()));
		System.out.println("remark:" + nutsFlowerChocolateCake.getRemark());
		// 吃蛋糕的感受已經發生了改變。
		System.out.println("impression:"
				+ nutsFlowerChocolateCake.getImpression());
	}
}
remark:乳酪蛋糕+一朵玫瑰花+一顆果仁
impression:乳酪蛋糕,香甜感受,看到一朵花真是happy,看到一顆果仁,哈哈
四、優缺點
      優點
(1)裝飾模式與繼承關係的目的都是要擴充套件物件的功能,但是裝飾模式可以提供比繼承更多的靈活性。裝飾模式允許系統動態決定“貼上”或者除掉一個“裝飾”,繼承關係是靜態的,它在系統執行前就決定了;
    (2)通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行為的組合;
    (3)裝飾者類可以在被裝飾者的行為前面或後面加上自己的行為,甚至取代被裝飾者的行為,達到特定的目的;
    (4)裝飾者一般對元件的客戶是透明的,除非客戶程式依賴於元件的具體型別
     缺點:由於使用裝飾模式,可以比使用繼承關係需要較少數目的類。使用較少的類,當然使設計比較易於進行。但是,在另一方面,使用裝飾模式會產生比使用繼承關係更多的物件。更多的物件會使得查錯變得困難,特別是這些物件看上去都很相像。
五、適用場景
      1)在不影響其他物件的情況下,以動態、透明的方式給單個物件新增職責;
      2)處理那些可以撤銷的職責;
      3)當不能採用生成子類的方式進行擴充時。
六、裝飾器模式與介面卡模式的比較
     共同點
:都擁有一個目標物件。裝飾器通過包裝一個裝飾物件來擴充套件其功能,而又不改變其介面,這實際上是基於物件的介面卡模式的一種變種。
     不同點:介面卡模式需要實現另外一個介面,而裝飾器模式必須實現該物件的介面。介面卡模式主要是為了介面的轉換,而裝飾者模式關注的是通過組合來動態的為被裝飾者注入新的功能或行為(即所謂的責任)。

相關推薦

Java裝飾模式(Decorator)

一、概述       裝飾模式又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴充套件物件的功能,可以在不建立更多子類的情況下,將物件的功能加以擴充套件,是繼承關係的一個替代方案。用意:動態地為物件新增一些額外的功能,就好比為房子進行裝修一樣。       特點

設計模式入門之裝飾模式Decorator

gravity 減少 都是 一個人 額外 不同的 這也 sys 裝飾器模式 //裝飾模式定義:動態地給一個對象加入一些額外的職責。 //就添加功能來說,裝飾模式比生成子類更為靈活 //這也提現了面向對象設計中的一條基本原則,即:盡量使用對象組合。而不是對象繼承//Com

設計模式(八)裝飾模式Decorator(結構型)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

設計模式-裝飾模式(Decorator)

裝飾器模式 定義:用於替代繼承,無需通過繼承增加子類就能擴充套件物件的新功能。 作用:用於包裝原有的類,並在保持類方法簽名完整性的前提下,提供額外的功能。 優劣: 優點: 裝飾類和被裝飾類可以獨立發展,不會耦合,裝飾器模式是繼承的一個替代方案,

裝飾模式 Decorator 結構型 設計模式 (十)

引子 現實世界的裝飾器模式 大家應該都吃過手抓餅,本文裝飾器模式以手抓餅為模型展開簡介 "老闆,來一個手抓餅,  加個培根,  加個雞蛋,多少錢?" 這句話會不會很耳熟,或者自己可能都說過呢? 我們看看這句話到底表達了哪些含義

java 裝飾模式

近期對java的只是做一個整理和複習:發現原來io流是裝飾器模式:具體如下 程式IO的關鍵在於建立BufferedReader物件br:     BufferedReader br = new BufferedReader(new FileReader("file.txt"

09.Javascript設計模式裝飾模式----Decorator

引入正題,本文將以我這段時間對裝飾者模式的學習、理解為基礎,向大家介紹Javascript設計模式中的裝飾器模式。我的理解程度非常有限,因此文件也不會描述的非常的周全,還請您做好心理準備。 裝飾器模式的概念 裝飾器模式動態地將職責附加到某物件上,讓該物件具備了其原本不具備的一些特性。其有別於類繼承,因為在

Java 裝飾模式詳解

前言 在上面的幾篇文章中,著重介紹了java 中常見的 IO 相關知識,在學習的過程中,發現 IO 包中是用了大量的裝飾器模式,為了徹底的學習 IO,今天就來揭開裝飾器模式的面紗。 為了弄明白裝飾器模式的本質,我查看了很多資料,發現有很多文章要麼說的很苦澀,要麼舉的例

重走Java設計模式——裝飾模式Decorator Pattern)

裝飾器模式 定義 裝飾器模式(Decorator Pattern)允許向一個現有的物件新增新的功能,同時又不改變其結構。這種型別的設計模式屬於結構型模式,它是作為現有的類的一個包裝。 這種模式建立了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外

java設計模式裝飾模式

rac 都在 通過 div 過濾 一個人 創建 展開 out 裝飾器模式 裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。 這種類型的設計模式屬於結構型模式,它是作為現有的類的一個包裝。 這種模式創建了一個裝飾類,用來包

java設計模式裝飾模式

食物 implement super map 結束 同時 ring 接口 包裝 適AT java設計模式之 裝飾器模式 裝飾器模式 裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。 這種類型的設計模式

java裝飾模式

args pattern lte auto eight pro 簡單的 add con Decorator Pattern(裝飾器模式),定義:Attach additional responsibilities to an object dynamically. Deco

Java設計模式(9)----------裝飾模式

tor 畫框 imp 橋接 好的 找到 strac 想是 bstr 1、介紹 裝飾器模式是一種結構型的設計模式。使用該模式的目的是為了較為靈活的對類進行擴展,而且不影響原來類的結構。有同學說可以通過繼承的方式進行實現啊,沒錯,繼承的確可以實現,但是繼承的成本相對比較高,

設計模式 —— 裝飾模式Decorator Pattern)

trac 價格 div desc number one 添加 imp esc 裝飾器模式(Decorator Pattern) 概念 裝飾器模式 允許向一個現有的對象添加新的功能,同時又不改變其結構。裝飾者可以在所委托被裝飾者的行為之前或之後加上自己的行為,以達到特定

設計模式裝飾Decorator模式

讓我 分享圖片 底部 .com 一件事 輸出 PE 新的 int 設計模式:裝飾器(Decorator)模式 一、前言 裝飾器模式也是一種非常重要的模式,在Java以及程序設計中占據著重要的地位。比如Java的數據流處理,我們可能看到數據流經過不同的類的包裝和包裹,最

Java進階篇設計模式之五-----外觀模式裝飾模式

和我 logs 適配器模式 del xtra implement () 實例化 網絡遊戲 前言 在上一篇中我們學習了結構型模式的適配器模式和橋接模式。本篇則來學習下結構型模式的外觀模式和裝飾器模式。 外觀模式 簡介 外觀模式隱藏系統的復雜性,並向客戶端提供了一個客戶端可以

java設計模式4.介面卡模式裝飾模式

介面卡模式 把一個類的介面變換成客戶端所期待的另一種介面,從而使原本因介面不匹配而無法在一起工作的兩個類能夠工作。 1. 類的介面卡模式 目標角色:期望的介面,對於類的介面卡模式,此角色不可以是具體類。 源角色:需要適配的介面。 介面卡角色:把源介面轉換成目標介面,此角色必須是具

Java設計模式從精通到入門二 裝飾模式

介紹 ​ 我儘量用最少的語言解釋總結: ​ Java23種設計模式之一,屬於結構型模式,允許向一個現有的物件新增新的功能,不改變其結構。 應用例項: ​ 給英雄聯盟種的射手,新增不同的裝備。先裝備攻速鞋,在裝備電刀,最後裝備無盡 uml類圖如下 主要程式碼如下 ADC類: /** *

設計模式(7)—— 結構型 —— 裝飾Decorator

介紹 定義:在不改變原有物件基礎之上,將功能附加到物件上 說明:在擴充套件原有物件功能方面,提供了比繼承更有彈性的替代方案 型別:結構型 適用場景: 擴充套件一個類的功能或給一個類新增附加職責 動態地給一個

Java設計模式 - 裝飾模式

 裝飾器模式 裝飾器模式就是在不改變原來設計的同時,動態的給物件新增一些額外的功能(加強原來的功能/拓展原來物件沒有的功能)。 UML圖示 裝飾器模式中的角色 抽象元件(Component):抽象類,規定了被裝飾者需要進行修飾的方法。 具體元件(Compone