溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java的23種設(shè)計模式,詳細(xì)講解(三)

發(fā)布時間:2020-07-21 10:49:07 來源:網(wǎng)絡(luò) 閱讀:304 作者:Java筆記丶 欄目:編程語言

本人免費(fèi)整理了Java高級資料,涵蓋了Java、RedisMongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并發(fā)分布式等教程,一共30G,需要自己領(lǐng)取。
傳送門:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q

1. 適配器(Adapter)

Intent

把一個類接口轉(zhuǎn)換成另一個用戶需要的接口。


Java的23種設(shè)計模式,詳細(xì)講解(三)



Class Diagram


Java的23種設(shè)計模式,詳細(xì)講解(三)



Implementation

鴨子(Duck)和火雞(Turkey)擁有不同的叫聲,Duck 的叫聲調(diào)用 quack() 方法,而 Turkey 調(diào)用 gobble() 方法。

要求將 Turkey 的 gobble() 方法適配成 Duck 的 quack() 方法,從而讓火雞冒充鴨子!

public?interface?Duck?{
????void?quack();}public?interface?Turkey?{
????void?gobble();}public?class?WildTurkey?implements?Turkey?{
????@Override
????public?void?gobble()?{
????????System.out.println("gobble!");
????}}public?class?TurkeyAdapter?implements?Duck?{
????Turkey?turkey;

????public?TurkeyAdapter(Turkey?turkey)?{
????????this.turkey?=?turkey;
????}

????@Override
????public?void?quack()?{
????????turkey.gobble();
????}}public?class?Client?{
????public?static?void?main(String[]?args)?{
????????Turkey?turkey?=?new?WildTurkey();
????????Duck?duck?=?new?TurkeyAdapter(turkey);
????????duck.quack();
????}}

JDK

  • java.util.Arrays#asList()

  • java.util.Collections#list()

  • java.util.Collections#enumeration()

  • javax.xml.bind.annotation.adapters.XMLAdapter

2. 橋接(Bridge)

Intent

將抽象與實現(xiàn)分離開來,使它們可以獨立變化。

Class Diagram

  • Abstraction:定義抽象類的接口

  • Implementor:定義實現(xiàn)類接口


Java的23種設(shè)計模式,詳細(xì)講解(三)



Implementation

RemoteControl 表示遙控器,指代 Abstraction。

TV 表示電視,指代 Implementor。

橋接模式將遙控器和電視分離開來,從而可以獨立改變遙控器或者電視的實現(xiàn)。

public?abstract?class?TV?{
????public?abstract?void?on();

????public?abstract?void?off();

????public?abstract?void?tuneChannel();}public?class?Sony?extends?TV?{
????@Override
????public?void?on()?{
????????System.out.println("Sony.on()");
????}

????@Override
????public?void?off()?{
????????System.out.println("Sony.off()");
????}

????@Override
????public?void?tuneChannel()?{
????????System.out.println("Sony.tuneChannel()");
????}}public?class?RCA?extends?TV?{
????@Override
????public?void?on()?{
????????System.out.println("RCA.on()");
????}

????@Override
????public?void?off()?{
????????System.out.println("RCA.off()");
????}

????@Override
????public?void?tuneChannel()?{
????????System.out.println("RCA.tuneChannel()");
????}}public?abstract?class?RemoteControl?{
????protected?TV?tv;

????public?RemoteControl(TV?tv)?{
????????this.tv?=?tv;
????}

????public?abstract?void?on();

????public?abstract?void?off();

????public?abstract?void?tuneChannel();}public?class?ConcreteRemoteControl1?extends?RemoteControl?{
????public?ConcreteRemoteControl1(TV?tv)?{
????????super(tv);
????}

????@Override
????public?void?on()?{
????????System.out.println("ConcreteRemoteControl1.on()");
????????tv.on();
????}

????@Override
????public?void?off()?{
????????System.out.println("ConcreteRemoteControl1.off()");
????????tv.off();
????}

????@Override
????public?void?tuneChannel()?{
????????System.out.println("ConcreteRemoteControl1.tuneChannel()");
????????tv.tuneChannel();
????}}public?class?ConcreteRemoteControl2?extends?RemoteControl?{
????public?ConcreteRemoteControl2(TV?tv)?{
????????super(tv);
????}

????@Override
????public?void?on()?{
????????System.out.println("ConcreteRemoteControl2.on()");
????????tv.on();
????}

????@Override
????public?void?off()?{
????????System.out.println("ConcreteRemoteControl2.off()");
????????tv.off();
????}

????@Override
????public?void?tuneChannel()?{
????????System.out.println("ConcreteRemoteControl2.tuneChannel()");
????????tv.tuneChannel();
????}}public?class?Client?{
????public?static?void?main(String[]?args)?{
????????RemoteControl?remoteControl1?=?new?ConcreteRemoteControl1(new?RCA());
????????remoteControl1.on();
????????remoteControl1.off();
????????remoteControl1.tuneChannel();
????????RemoteControl?remoteControl2?=?new?ConcreteRemoteControl2(new?Sony());
?????????remoteControl2.on();
?????????remoteControl2.off();
?????????remoteControl2.tuneChannel();
????}}

JDK

  • AWT (It provides an abstraction layer which maps onto the native OS the windowing support.)

  • JDBC

3. 組合(Composite)

Intent

將對象組合成樹形結(jié)構(gòu)來表示“整體/部分”層次關(guān)系,允許用戶以相同的方式處理單獨對象和組合對象。

Class Diagram

組件(Component)類是組合類(Composite)和葉子類(Leaf)的父類,可以把組合類看成是樹的中間節(jié)點。

組合對象擁有一個或者多個組件對象,因此組合對象的操作可以委托給組件對象去處理,而組件對象可以是另一個組合對象或者葉子對象。


Java的23種設(shè)計模式,詳細(xì)講解(三)



Implementation

public?abstract?class?Component?{
????protected?String?name;

????public?Component(String?name)?{
????????this.name?=?name;
????}

????public?void?print()?{
????????print(0);
????}

????abstract?void?print(int?level);

????abstract?public?void?add(Component?component);

????abstract?public?void?remove(Component?component);}public?class?Composite?extends?Component?{

????private?List<Component>?child;

????public?Composite(String?name)?{
????????super(name);
????????child?=?new?ArrayList<>();
????}

????@Override
????void?print(int?level)?{
????????for?(int?i?=?0;?i?<?level;?i++)?{
????????????System.out.print("--");
????????}
????????System.out.println("Composite:"?+?name);
????????for?(Component?component?:?child)?{
????????????component.print(level?+?1);
????????}
????}

????@Override
????public?void?add(Component?component)?{
????????child.add(component);
????}

????@Override
????public?void?remove(Component?component)?{
????????child.remove(component);
????}}public?class?Leaf?extends?Component?{
????public?Leaf(String?name)?{
????????super(name);
????}

????@Override
????void?print(int?level)?{
????????for?(int?i?=?0;?i?<?level;?i++)?{
????????????System.out.print("--");
????????}
????????System.out.println("left:"?+?name);
????}

????@Override
????public?void?add(Component?component)?{
????????throw?new?UnsupportedOperationException();?//?犧牲透明性換取單一職責(zé)原則,這樣就不用考慮是葉子節(jié)點還是組合節(jié)點????}

????@Override
????public?void?remove(Component?component)?{
????????throw?new?UnsupportedOperationException();
????}}public?class?Client?{
????public?static?void?main(String[]?args)?{
????????Composite?root?=?new?Composite("root");
????????Component?node1?=?new?Leaf("1");
????????Component?node2?=?new?Composite("2");
????????Component?node3?=?new?Leaf("3");
????????root.add(node1);
????????root.add(node2);
????????root.add(node3);
????????Component?node21?=?new?Leaf("21");
????????Component?node22?=?new?Composite("22");
????????node2.add(node21);
????????node2.add(node22);
????????Component?node221?=?new?Leaf("221");
????????node22.add(node221);
????????root.print();
????}}Composite:root--left:1--Composite:2----left:21----Composite:22------left:221--left:3

JDK

  • javax.swing.JComponent#add(Component)

  • java.awt.Container#add(Component)

  • java.util.Map#putAll(Map)

  • java.util.List#addAll(Collection)

  • java.util.Set#addAll(Collection)

4. 裝飾(Decorator)

Intent

為對象動態(tài)添加功能。

Class Diagram

裝飾者(Decorator)和具體組件(ConcreteComponent)都繼承自組件(Component),具體組件的方法實現(xiàn)不需要依賴于其它對象,而裝飾者組合了一個組件,這樣它可以裝飾其它裝飾者或者具體組件。所謂裝飾,就是把這個裝飾者套在被裝飾者之上,從而動態(tài)擴(kuò)展被裝飾者的功能。裝飾者的方法有一部分是自己的,這屬于它的功能,然后調(diào)用被裝飾者的方法實現(xiàn),從而也保留了被裝飾者的功能??梢钥吹?,具體組件應(yīng)當(dāng)是裝飾層次的最低層,因為只有具體組件的方法實現(xiàn)不需要依賴于其它對象。


Java的23種設(shè)計模式,詳細(xì)講解(三)



Implementation

設(shè)計不同種類的飲料,飲料可以添加配料,比如可以添加牛奶,并且支持動態(tài)添加新配料。每增加一種配料,該飲料的價格就會增加,要求計算一種飲料的價格。

下圖表示在 DarkRoast 飲料上新增新添加 Mocha 配料,之后又添加了 Whip 配料。DarkRoast 被 Mocha 包裹,Mocha 又被 Whip 包裹。它們都繼承自相同父類,都有 cost() 方法,外層類的 cost() 方法調(diào)用了內(nèi)層類的 cost() 方法。


Java的23種設(shè)計模式,詳細(xì)講解(三)



public?interface?Beverage?{
????double?cost();}public?class?DarkRoast?implements?Beverage?{
????@Override
????public?double?cost()?{
????????return?1;
????}}public?class?HouseBlend?implements?Beverage?{
????@Override
????public?double?cost()?{
????????return?1;
????}}public?abstract?class?CondimentDecorator?implements?Beverage?{
????protected?Beverage?beverage;}public?class?Milk?extends?CondimentDecorator?{

????public?Milk(Beverage?beverage)?{
????????this.beverage?=?beverage;
????}

????@Override
????public?double?cost()?{
????????return?1?+?beverage.cost();
????}}public?class?Mocha?extends?CondimentDecorator?{

????public?Mocha(Beverage?beverage)?{
????????this.beverage?=?beverage;
????}

????@Override
????public?double?cost()?{
????????return?1?+?beverage.cost();
????}}public?class?Client?{

????public?static?void?main(String[]?args)?{
????????Beverage?beverage?=?new?HouseBlend();
????????beverage?=?new?Mocha(beverage);
????????beverage?=?new?Milk(beverage);
????????System.out.println(beverage.cost());
????}}3.0

設(shè)計原則

類應(yīng)該對擴(kuò)展開放,對修改關(guān)閉:也就是添加新功能時不需要修改代碼。飲料可以動態(tài)添加新的配料,而不需要去修改飲料的代碼。

不可能把所有的類設(shè)計成都滿足這一原則,應(yīng)當(dāng)把該原則應(yīng)用于最有可能發(fā)生改變的地方。

JDK

  • java.io.BufferedInputStream(InputStream)

  • java.io.DataInputStream(InputStream)

  • java.io.BufferedOutputStream(OutputStream)

  • java.util.zip.ZipOutputStream(OutputStream)

  • java.util.Collections#checkedList|Map|Set|SortedSet|SortedMap

5. 外觀(Facade)

Intent

提供了一個統(tǒng)一的接口,用來訪問子系統(tǒng)中的一群接口,從而讓子系統(tǒng)更容易使用。

Class Diagram


Java的23種設(shè)計模式,詳細(xì)講解(三)



Implementation

觀看電影需要操作很多電器,使用外觀模式實現(xiàn)一鍵看電影功能。

public?class?SubSystem?{
????public?void?turnOnTV()?{
????????System.out.println("turnOnTV()");
????}

????public?void?setCD(String?cd)?{
????????System.out.println("setCD(?"?+?cd?+?"?)");
????}

????public?void?startWatching(){
????????System.out.println("startWatching()");
????}}public?class?Facade?{
????private?SubSystem?subSystem?=?new?SubSystem();

????public?void?watchMovie()?{
????????subSystem.turnOnTV();
????????subSystem.setCD("a?movie");
????????subSystem.startWatching();
????}}public?class?Client?{
????public?static?void?main(String[]?args)?{
????????Facade?facade?=?new?Facade();
????????facade.watchMovie();
????}}

設(shè)計原則

最少知識原則:只和你的密友談話。也就是說客戶對象所需要交互的對象應(yīng)當(dāng)盡可能少。

6. 享元(Flyweight)

Intent

利用共享的方式來支持大量細(xì)粒度的對象,這些對象一部分內(nèi)部狀態(tài)是相同的。

Class Diagram

  • Flyweight:享元對象

  • IntrinsicState:內(nèi)部狀態(tài),享元對象共享內(nèi)部狀態(tài)

  • ExtrinsicState:外部狀態(tài),每個享元對象的外部狀態(tài)不同


Java的23種設(shè)計模式,詳細(xì)講解(三)



Implementation

public?interface?Flyweight?{
????void?doOperation(String?extrinsicState);}public?class?ConcreteFlyweight?implements?Flyweight?{

????private?String?intrinsicState;

????public?ConcreteFlyweight(String?intrinsicState)?{
????????this.intrinsicState?=?intrinsicState;
????}

????@Override
????public?void?doOperation(String?extrinsicState)?{
????????System.out.println("Object?address:?"?+?System.identityHashCode(this));
????????System.out.println("IntrinsicState:?"?+?intrinsicState);
????????System.out.println("ExtrinsicState:?"?+?extrinsicState);
????}}public?class?FlyweightFactory?{

????private?HashMap<String,?Flyweight>?flyweights?=?new?HashMap<>();

????Flyweight?getFlyweight(String?intrinsicState)?{
????????if?(!flyweights.containsKey(intrinsicState))?{
????????????Flyweight?flyweight?=?new?ConcreteFlyweight(intrinsicState);
????????????flyweights.put(intrinsicState,?flyweight);
????????}
????????return?flyweights.get(intrinsicState);
????}}public?class?Client?{

????public?static?void?main(String[]?args)?{
????????FlyweightFactory?factory?=?new?FlyweightFactory();
????????Flyweight?flyweight1?=?factory.getFlyweight("aa");
????????Flyweight?flyweight2?=?factory.getFlyweight("aa");
????????flyweight1.doOperation("x");
????????flyweight2.doOperation("y");
????}}Object?address:?1163157884IntrinsicState:?aaExtrinsicState:?xObject?address:?1163157884IntrinsicState:?aaExtrinsicState:?y

JDK

Java 利用緩存來加速大量小對象的訪問時間。

  • java.lang.Integer#valueOf(int)

  • java.lang.Boolean#valueOf(boolean)

  • java.lang.Byte#valueOf(byte)

  • java.lang.Character#valueOf(char)

7. 代理(Proxy)

Intent

控制對其它對象的訪問。

Class Diagram

代理有以下四類:

  • 遠(yuǎn)程代理(Remote Proxy):控制對遠(yuǎn)程對象(不同地址空間)的訪問,它負(fù)責(zé)將請求及其參數(shù)進(jìn)行編碼,并向不同地址空間中的對象發(fā)送已經(jīng)編碼的請求。

  • 虛擬代理(Virtual Proxy):根據(jù)需要創(chuàng)建開銷很大的對象,它可以緩存實體的附加信息,以便延遲對它的訪問,例如在網(wǎng)站加載一個很大圖片時,不能馬上完成,可以用虛擬代理緩存圖片的大小信息,然后生成一張臨時圖片代替原始圖片。

  • 保護(hù)代理(Protection Proxy):按權(quán)限控制對象的訪問,它負(fù)責(zé)檢查調(diào)用者是否具有實現(xiàn)一個請求所必須的訪問權(quán)限。

  • 智能代理(Smart Reference):取代了簡單的指針,它在訪問對象時執(zhí)行一些附加操作:記錄對象的引用次數(shù);當(dāng)?shù)谝淮我靡粋€對象時,將它裝入內(nèi)存;在訪問一個實際對象前,檢查是否已經(jīng)鎖定了它,以確保其它對象不能改變它。


Java的23種設(shè)計模式,詳細(xì)講解(三)



Implementation

以下是一個虛擬代理的實現(xiàn),模擬了圖片延遲加載的情況下使用與圖片大小相等的臨時內(nèi)容去替換原始圖片,直到圖片加載完成才將圖片顯示出來。

public?interface?Image?{
????void?showImage();}public?class?HighResolutionImage?implements?Image?{

????private?URL?imageURL;
????private?long?startTime;
????private?int?height;
????private?int?width;

????public?int?getHeight()?{
????????return?height;
????}

????public?int?getWidth()?{
????????return?width;
????}

????public?HighResolutionImage(URL?imageURL)?{
????????this.imageURL?=?imageURL;
????????this.startTime?=?System.currentTimeMillis();
????????this.width?=?600;
????????this.height?=?600;
????}

????public?boolean?isLoad()?{
????????//?模擬圖片加載,延遲?3s?加載完成????????long?endTime?=?System.currentTimeMillis();
????????return?endTime?-?startTime?>?3000;
????}

????@Override
????public?void?showImage()?{
????????System.out.println("Real?Image:?"?+?imageURL);
????}}public?class?ImageProxy?implements?Image?{

????private?HighResolutionImage?highResolutionImage;

????public?ImageProxy(HighResolutionImage?highResolutionImage)?{
????????this.highResolutionImage?=?highResolutionImage;
????}

????@Override
????public?void?showImage()?{
????????while?(!highResolutionImage.isLoad())?{
????????????try?{
????????????????System.out.println("Temp?Image:?"?+?highResolutionImage.getWidth()?+?"?"?+?highResolutionImage.getHeight());
????????????????Thread.sleep(100);
????????????}?catch?(InterruptedException?e)?{
????????????????e.printStackTrace();
????????????}
????????}
????????highResolutionImage.showImage();
????}}public?class?ImageViewer?{

????public?static?void?main(String[]?args)?throws?Exception?{
????????String?image?=?"http://image.jpg";
????????URL?url?=?new?URL(image);
????????HighResolutionImage?highResolutionImage?=?new?HighResolutionImage(url);
????????ImageProxy?imageProxy?=?new?ImageProxy(highResolutionImage);
????????imageProxy.showImage();
????}}

JDK

  • java.lang.reflect.Proxy

  • RMI


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI