裝飾者模式
在科爾沁等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都做網(wǎng)站、成都網(wǎng)站制作 網(wǎng)站設(shè)計制作專業(yè)公司,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計,全網(wǎng)整合營銷推廣,外貿(mào)網(wǎng)站建設(shè),科爾沁網(wǎng)站建設(shè)費用合理。
1、意圖:?動態(tài)地給一個對象添加一些額外的職責。就增加功能來說, Decorator模式相比生成子類更為靈活。該模式以對客 戶端透明的方式擴展對象的功能。
2、適用環(huán)境
(1)在不影響其他對象的情況下,以動態(tài)、透明的方式給單個對象添加職責。
(2)處理那些可以撤消的職責。
(3)當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產(chǎn)生大量的 子類,使得子類數(shù)目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。
3、參與者
1.Component(被裝飾對象的基類)
定義一個對象接口,可以給這些對象動態(tài)地添加職責。
2.ConcreteComponent(具體被裝飾對象)
定義一個對象,可以給這個對象添加一些職責。
3.Decorator(裝飾者抽象類)
維持一個指向Component實例的引用,并定義一個與Component接口一致的接口。
4.ConcreteDecorator(具體裝飾者)
具體的裝飾對象,給內(nèi)部持有的具體被裝
飾對象,增加具體的職責。
4、類圖
5、涉及角色
(1)抽象組件:定義一個抽象接口,來規(guī)范準備附加功能的類
(2)具體組件:將要被附加功能的類,實現(xiàn)抽象構(gòu)件角色接口
(3)抽象裝飾者:持有對具體構(gòu)件角色的引用并定義與抽象構(gòu)件角色一致的接口
(4)具體裝飾:實現(xiàn)抽象裝飾者角色,負責對具體構(gòu)件添加額外功能。
裝飾者模式( )
裝飾者模式的核心思想在于 無需將所有的邏輯 即 核心內(nèi)容構(gòu)建 HTML文本構(gòu)造和HTTP頭生成等 個功能模塊粘合在一起實現(xiàn) 通過裝飾者模式 可以將它們分解為 個幾乎完全獨立的組件 并在使用時靈活地進行裝配 為實現(xiàn)這個功能 可以使用如圖 所示的結(jié)構(gòu)
圖 ? 裝飾者模式示例
IPacketCreator即裝飾接口 用于處理具體的內(nèi)容 PacketBodyCreator是具體的組件 它的功能是構(gòu)造要發(fā)布信息的核心內(nèi)容 但是它不負責將其構(gòu)造成一個格式工整 可直接發(fā)布的數(shù)據(jù)格式 PacketHTTPHeaderCreator負責對給定的內(nèi)容加上HTTP頭部 PacketHTMLHeaderCreator負責將給定的內(nèi)容格式化成HTML文本 如圖 所示 個功能模塊相對獨立且分離 易于系統(tǒng)維護
IPacketCreator的實現(xiàn)很簡單 它是一個單方法的接口
public interface IPacketCreator {
public String handleContent() ????????? //用于內(nèi)容處理
}
PacketBodyCreator用于返回數(shù)據(jù)包的核心數(shù)據(jù)
public class PacketBodyCreator implements IPacketCreator{
@Override
public String handleContent() {
return Content of Packet ;???? //構(gòu)造核心數(shù)據(jù) 但不包括格式
}
}
PacketDecorator維護核心組件ponent對象 它負責告知其子類 其核心業(yè)務(wù)邏輯應(yīng)該全權(quán)委托ponent完成 自己僅僅是做增強處理
public abstract class PacketDecorator implements IPacketCreator{
IPacketCreator ponent;
public PacketDecorator(IPacketCreator c){
cponent=c;
}
}
PacketHTMLHeaderCreator是具體的裝飾器 它負責對核心發(fā)布的內(nèi)容進行HTML格式化操作 需要特別注意的是 它委托了具體組件ponent進行核心業(yè)務(wù)處理
public class PacketHTMLHeaderCreator extends PacketDecorator{
public PacketHTMLHeaderCreator(IPacketCreator c) {
super(c)
}
@Override
public String handleContent() {???????? //將給定數(shù)據(jù)封裝成HTML
StringBuffer *** =new StringBuffer()
*** append( )
*** append( body )
*** append(ponent handleContent())
*** append( /body )
*** append( /\n )
return *** toString()
}
}
返回目錄 Java程序性能優(yōu)化 讓你的Java程序更快 更穩(wěn)定
編輯推薦
Java程序設(shè)計培訓(xùn)視頻教程
J EE高級框架實戰(zhàn)培訓(xùn)視頻教程
J ME移動開發(fā)實戰(zhàn)教學(xué)視頻
Visual C++音頻/視頻技術(shù)開發(fā)與實戰(zhàn)
Oracle索引技術(shù)
lishixinzhi/Article/program/Java/gj/201311/27823
java decaf是什么,讓我們一起了解一下?
decaf是一般視覺識別的深度卷積刺激特征,decaf是一個開放源代碼,實現(xiàn)了這些深層卷積激活特性,以及所有相關(guān)的網(wǎng)絡(luò)參數(shù),使視覺研究人員能夠在一系列視覺概念學(xué)習(xí)范例中進行深層表征的實驗。
那如何正確高效理解decaf讓我們更好的認知和學(xué)習(xí)呢?
我們通過學(xué)習(xí)設(shè)計模式之裝飾者模式來系統(tǒng)了解。
首先裝飾者模式是動態(tài)地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
我們要以飲料為主體,然后在運行時以調(diào)料來“裝飾”(decorate)飲料。比方說,如果顧客想要摩卡和奶泡深焙咖啡,那么,要做的是:
1、拿一個深焙咖啡(DarkRoast)對象
2、以摩卡(Mocha)對象裝飾它
3、以奶泡(Whip)對象裝飾它
4、調(diào)用cost()方法,并依賴委托(delegate)將調(diào)料的價錢加上去。
但是如何“裝飾”一個對象,而“委托”又要如何與此搭配使用呢?那就是把裝飾者對象當成“包裝者”,讓我們看看這是如何工作的:
1、以DarkRoast對象開始。
2、顧客想要摩卡(Mocha),所以建立一個 Mocha對象,并用它將DarkRoast對象包(wrap)起來。Mocha對象是一個裝飾者,它的類型“反映”了它所裝飾的對象(本例中,就是 Beverage)。所謂的“反映”,指的就是兩者類型一致。
所以Mocha也有一個cost()方法。通過多態(tài),也可以把Mocha所包裹的任何Beverage當成DarkRoast是Beverage(因為Mocha是Beverage的子類
型)。
3、顧客也想要奶泡(Whip),所以需要建立一個Whip裝飾者,并用它將Mocha對象包起來。別忘了,DarkRoast繼承自Beverage,且有一個cost()方法,用來計算飲料價錢。Whip是一個裝飾者,所以它也 反映了DarkRoast類型,并包括一Mocha 個cost()方法。?
4、現(xiàn)在,該是為顧客算錢的時候了。通過調(diào)用最外圈裝飾者(Whip)的cost()就可以辦得到。Whip的cost()會先委托它裝飾的對象(也就是Mocha)計算出價錢,然后再加上奶泡的價錢。
代碼實現(xiàn):
/** ?*?@author?fan_rc@suixingpay.com ?*?@description?飲料抽象類 ?*?@date?2019/9/17?20:53 ?*/ public?abstract?class?Beverage?{ ????String?description?=?"Unknown?Beverage"; ????public?String?getDescription()?{ ????????return?description; ????} ????/** ?????*?cost方法是用來返回飲料的價錢(需在具體類中自己實現(xiàn)) ?????* ?????*?@return ?????*/ ????public?abstract?BigDecimal?cost();
裝飾者模式用來擴展對象的功能,給對象添加不同的功能。
在io流中,比如
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("d:/text.txt"))));
這種對File類的包裝,由內(nèi)層到外層擴展輸入流的功能,就是一個典型的裝飾者模式。inputstream是被裝飾對象,然后Fileinputstream、InputStream、BufferedReader都是它的裝飾器,用來擴展它的功能!
DataInputStream?bis?=?new?DataInputStream(new?BufferedInputStream(new?FileInputStream("File")));
BufferedInputStream?bis2?=?new?BufferedInputStream(new?DataInputStream(new?FileInputStream("File")));
BufferedInputStream添加了緩沖功能,請問,bis還有緩沖功能么?bis現(xiàn)在是DataInputStream類型的,bis2才是BufferedInputStream類型的,這是我學(xué)些IO的一個問題,為什么bis還有緩沖功能?
問題:動態(tài)給一個對象添加一些額外的職責
思考:可以修改這個類的源代碼嗎?
回答:可以
思考:那直接修改源代碼就行了
問題:如果不可以修改呢?
思考:如果不可以修改源代碼,那怎么添加?
回答:有一些類庫可以直接修改編譯后的class文件,但是這里不考慮
? ? ?可以直接包含這個類的對象,如果這個類有實現(xiàn)某些接口,剛好某個需要添加額外智能的方法正好是其中一個方法,那就好辦了
Son這個類的paint()方法需要添加一些額外的功能
package?decorator;
public?class?Son?implements?Work?{
public?void?paint()?{
System.out.println("兒子用鉛筆畫好了一幅畫。");
}
}
這個類不是實現(xiàn)了Work方法嗎?那就好辦了,新建一個類,繼承Work接口:
package?decorator;
public?class?Mother?implements?Work?{
//被裝飾者
private?Work?work;
public?Mother(Work?work)?{
this.work?=?work;
}
private?Mother()?{}
public?void?paint()?{
//媽媽裝飾者做的職責
System.out.println("媽媽正在做給畫上顏色前的準備工作。");
//被裝飾者做的職責
work.paint();
//媽媽裝飾者做的職責
System.out.println("媽媽給畫上好了顏色。");
}
}
那個所謂的Work接口:
package?decorator;
public?interface?Work?{
public?void?paint();
}
你不是想讓Son可以的paint方法多做點工作么?那我new出Mother類執(zhí)行paint方法不就可以了嗎
看代碼就知道,其實這個裝飾器模式并不怎么好用,每個需要裝飾的類或者需要繼承某個接口,這實在是一個限制
網(wǎng)上找的資料:
裝飾模式(Decorator)
裝飾模式又名包裝(Wrapper)模式。
裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關(guān)系的一個替代方案。
裝飾模式通過創(chuàng)建一個包裝對象,也就是裝飾,來包裹真實的對象。
裝飾模式以對客戶端透明的方式動態(tài)地給一個對象附加上更多的責任。換言之,客戶端并不會覺得對象在裝飾前和裝飾后有什么不同。
裝飾模式可以在不創(chuàng)造更多子類的情況下,將對象的功能加以擴展。
裝飾模式把客戶端的調(diào)用委派到被裝飾類。裝飾模式的關(guān)鍵在于這種擴展是完全透明的。
裝飾模式的角色
抽象構(gòu)件角色(Component):給出一個抽象接口,以規(guī)范準備接收附加責任的對象。
具體構(gòu)件角色(Concrete Component):定義將要接收附加責任的類。
裝飾角色(Decorator):持有一個構(gòu)件(Component)對象的引用,并定義一個與抽象構(gòu)件接口一致的接口。
具體裝飾角色(Concrete Decorator):負責給構(gòu)件對象“貼上”附加的責任。
Java IO中的裝飾模式
在IO中,具體構(gòu)件角色是節(jié)點流,裝飾角色是過濾流。
FilterInputStream和FilterOutputStream是裝飾角色,而其他派生自它們的類則是具體裝飾角色。
裝飾模式的特點
裝飾對象和真實對象有相同的接口。這樣客戶端對象就可以以和真實對象相同的方式和裝飾對象交互。
裝飾對象包含一個真實對象的引用(reference)。
裝飾對象接收所有來自客戶端的請求,它把這些請求轉(zhuǎn)發(fā)給真實的對象。
裝飾對象可以在轉(zhuǎn)發(fā)這些請求之前或之后附加一些功能。
這樣就確保了在運行時,不用修改給定對象的結(jié)構(gòu)就可以在外部增加附加的功能。
程序?qū)嵗?/p>
public?interface?Component
{
public?void?doSomething();
}
這是抽象構(gòu)件角色,是一個接口。具體構(gòu)件角色實現(xiàn)這個接口:
public?class?ConcreteComponent?implements?Component
{
@Override
public?void?doSomething()
{
System.out.println("功能A");
}
}
裝飾角色:
public?class?Decorator?implements?Component
{
private?Component?component;
public?Decorator(Component?component)
{
this.component?=?component;
}
@Override
public?void?doSomething()
{
component.doSomething();
}
}
其中包含了構(gòu)件角色的引用,方法調(diào)用中利用構(gòu)件角色的方法。
具體裝飾角色(兩個):
public?class?ConcreteDecorator1?extends?Decorator
{
public?ConcreteDecorator1(Component?component)
{
super(component);
}
@Override
public?void?doSomething()
{
super.doSomething();
this.doAnotherThing();
}
private?void?doAnotherThing()
{
System.out.println("功能B");
}
}
public?class?ConcreteDecorator2?extends?Decorator
{
public?ConcreteDecorator2(Component?component)
{
super(component);
}
@Override
public?void?doSomething()
{
super.doSomething();
this.doAnotherThing();
}
private?void?doAnotherThing()
{
System.out.println("功能C");
}
}
使用測試:
public?class?Client
{
public?static?void?main(String[]?args)
{
Component?component?=?new?ConcreteComponent();
Component?component1?=?new?ConcreteDecorator1(component);
component1.doSomething();
System.out.println("-----------");
Component?component2?=?new?ConcreteDecorator2(component1);
component2.doSomething();
}
}
輸出:
功能A
功能B
-----------
功能A
功能B
功能C