摘要:工廠設(shè)計模式工廠設(shè)計模式,主要用于進(jìn)行實(shí)例化對象時的解耦操作,避免使用關(guān)鍵字實(shí)例化對象,通過反射,根據(jù)類名稱動態(tài)創(chuàng)建對象示例靜態(tài)工廠模式構(gòu)造方法私有化獲取指定類名稱的對象動態(tài)代理模式動態(tài)代理模式,主要用于對同一接口子類的相同邏輯進(jìn)行代理操作
工廠設(shè)計模式
工廠設(shè)計模式,主要用于進(jìn)行實(shí)例化對象時的解耦操作,避免使用new關(guān)鍵字實(shí)例化對象,通過反射,根據(jù)類名稱動態(tài)創(chuàng)建對象
示例:
package design; /** *靜態(tài)工廠模式 */ public class Factory { /** *構(gòu)造方法私有化 */ private Factory (){ } /** * 獲取指定類名稱的對象 * @param className * @param動態(tài)代理模式* @return T */ public static T getInstance(String className){ T object =null; try { object = (T) Class.forName(className).newInstance(); }catch (Exception e){ e.printStackTrace(); } return object; } }
動態(tài)代理模式,主要用于對同一接口子類的相同邏輯進(jìn)行代理操作
示例:
package design; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 動態(tài)代理模式 */ public class DynamicProxy implements InvocationHandler { private Object target; /** * 代理的目標(biāo)對象 * @param target * @return */ public Object proxy(Object target){ this.target=target; return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } /** * 目標(biāo)方法執(zhí)行前執(zhí)行 * @param object */ public void before(Object object){ System.out.println("目標(biāo)方法執(zhí)行前執(zhí)行"); } /** * 目標(biāo)方法執(zhí)行后執(zhí)行 * @param object */ public void after(Object object){ System.out.println("目標(biāo)方法執(zhí)行后執(zhí)行"); } /** * Processes a method invocation on a proxy instance and returns * the result. This method will be invoked on an invocation handler * when a method is invoked on a proxy instance that it is * associated with. * @param proxy * @param method * @param args * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { this.before(proxy); Object result =method.invoke(proxy,args); this.after(result); return result; } }單例模式一
單例模式一:采用static final 修飾在類內(nèi)部實(shí)例化的對象,保證對象的唯一性,此種方式,實(shí)在類加載的過程中實(shí)例化對象,無論是否使用,都會實(shí)例化。
示例
package design; /** * 單例模式一 */ public class SingletonOne { /** * 實(shí)例化對象唯一 */ private static final SingletonOne INSTANCE =new SingletonOne(); /** * 構(gòu)造方法私有化 */ private SingletonOne(){ } /** * 獲取單例對象 * @return */ public static SingletonOne getInstance(){ return INSTANCE; } }單例模式二
單例模式二:采用volatile關(guān)鍵字修飾實(shí)例化對象,并通過同步鎖(鎖Class)的形式,保證實(shí)例化對象的唯一性,此方式在第一次使用時進(jìn)行實(shí)例化
volatile關(guān)鍵字修飾的變量與普通變量的讀取方式不同
volatile定義的變量,將直接使用原始數(shù)據(jù)進(jìn)行處理,更改后立即生效
示例
package design; /** * 單例模式二 */ public class SingletonTwo { /** * 使用volatile關(guān)鍵字修飾單例對象 * volatile定義的變量,將直接使用原始數(shù)據(jù)進(jìn)行處理,更改后立即生效 */ public static volatile SingletonTwo instance; /** * 構(gòu)造方法私有化 */ private SingletonTwo(){ } /** * 獲取單例對象 * @return */ public static SingletonTwo getInstance(){ if(instance ==null){ //通過同步鎖住當(dāng)前類,來保證線程安全,并提高性能,若直接同步該方法,會大大降低性能 synchronized (SingletonTwo.class){ if (instance ==null){ instance =new SingletonTwo(); } } } return instance; } }單例模式三
單例模式三:基于Jvm類加載機(jī)制實(shí)現(xiàn)單例
示例
/** * 單例模式三 */ public class ClassSingletonDemo { /** * 構(gòu)造方法私有化 */ private ClassSingletonDemo(){}; /** * 靜態(tài)方法獲取實(shí)例 */ public static ClassSingletonDemo getInstance(){ return SingletonHandler.singleton; } /** * 內(nèi)部靜態(tài)類保證只初始化一次 */ private static class SingletonHandler { private static ClassSingletonDemo singleton = new ClassSingletonDemo(); static { System.out.println("This"s innerClass"s static code block"); } } }單例模式四
單例模式四:基于Enum類型的加載機(jī)制實(shí)現(xiàn)單例
示例
/** * 單例模式四 */ public class EnumSingletonDemo { /** * 構(gòu)造方法私有化 */ private EnumSingletonDemo(){} /** * 靜態(tài)方法獲取實(shí)例 */ public static EnumSingletonDemo getInstance(){ return Singleton.INSTANCE.getInstance(); } /** * 私有枚舉,只被JVM加載一次,只實(shí)例化一次 */ private enum Singleton{ INSTANCE; private EnumSingletonDemo singleton; Singleton(){ singleton = new EnumSingletonDemo(); } public EnumSingletonDemo getInstance(){ return singleton; } } }中介者模式
中介者模式的定義:用一個中介對象來封裝一些列的對象交互,中介者使得各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。中介者模式解決問題的思路很簡單,就是通過引入一個中介對象,讓其他對象只與中介對象交互,而中介對象知道如何和其他所有對象的交互,這樣對象之間的交互關(guān)系就沒有了,從而實(shí)現(xiàn)了對象之間的解耦。由此,我們也可以看出一個問題,那就是中介對象控制著整個系統(tǒng)的邏輯,它會過于復(fù)雜,這是一個缺點(diǎn)。中介者模式的本質(zhì)是封裝交互:
(1)對象在自身狀態(tài)發(fā)生改變時報告給中介對象;
(2)中介對象控制著整個系統(tǒng)的邏輯,它知道如何與所有對象交互;
(3)對象需要對中介對象發(fā)出的請求作出回應(yīng)。
中介者模式中的角色:
Mediator:中介者接口,定義各個同事之間交互所需要的方法;
ConcreteMediator:具體的中介者,它需要了解并維護(hù)各個同事對象,并負(fù)責(zé)具體的協(xié)調(diào)各同事對象的交互關(guān)系;
Colleague:所有同事對象的父類,一般實(shí)現(xiàn)成抽象類,主要負(fù)責(zé)約束同事對象的類型,并負(fù)責(zé)實(shí)現(xiàn)一些公共功能;
ConcreteMediator:具體的同事類,實(shí)現(xiàn)自己的業(yè)務(wù),當(dāng)需要與其他同事對象通信時,就與持有的中介者通信,中介者會負(fù)責(zé)與其他同事的交互。在標(biāo)準(zhǔn)的中介者模式中,將使用中介者來交互的那些對象叫做同事類,它們繼承自相同的父類,所以叫做同事。正是由于它們之間的交互很復(fù)雜,所以才產(chǎn)生了把這些交互關(guān)系分離出去,讓中介者來處理。
示例:
以電腦來看電影為例子,首先光驅(qū)從光盤中讀取數(shù)據(jù),然后通知CPU將數(shù)據(jù)分離成音頻和視頻,CPU處理完畢后再分別將數(shù)據(jù)傳送給聲卡和顯卡進(jìn)行播放。從上面的描述的中發(fā)現(xiàn),光驅(qū)盒CPU是耦合的,CPU又和聲卡顯卡是耦合的,怎么解耦的呢?如果使用中介者模式,通過引入主板作為中介者,所有的對象都與主板交互,那么播放電影的流程就變成了這樣:
(1)光驅(qū)從光盤讀取到數(shù)據(jù),通知主板,數(shù)據(jù)準(zhǔn)備好了;
(2)主板收到光驅(qū)的請求后,將原始數(shù)據(jù)傳給CPU,讓它將數(shù)據(jù)分離成音頻和視頻;
(3)CPU將數(shù)據(jù)分離后,通知主板,數(shù)據(jù)分離完畢;
(4)主板收到CPU通知后,分別將音頻和視頻傳給聲卡和顯卡;
(5)聲卡和顯卡同時播放。
這樣一個過程中,所有的類只與主板耦合,而不與其他類保持關(guān)系,做到了解耦,而且過程很清晰。實(shí)際上計算機(jī)硬件就是這樣通信的,只不過更復(fù)雜一些,所以這些東西都是相通的,重要的是思想。
Java實(shí)現(xiàn):
同事對象的父類
package design; /** * 同事對象的父類,一般實(shí)現(xiàn)成抽象類,用于約束同事對象的類型 * 同時實(shí)現(xiàn)一些功能公共方法,例如持有中介者對象 */ public abstract class Colleague { //所有的同事對象都需要持有中介對象 private Mediator mediator; public Colleague(Mediator mediator) { this.mediator = mediator; } public Mediator getMediator() { return mediator; } }
中介者接口
package design; /** * 中介者接口 */ public interface Mediator { /** * 同事對象自身狀態(tài)改變時,通過這個方法通知中介者對象 * @param obj */ public void changed(Colleague obj); /** * 中介者對象需要知道所有同事對象 * @param instance */ public void setCDDriver(CDDriver instance); public void setCPU(CPU instance); public void setVideoCard(Video instance); public void setSoundCard(Sound instance); }
光驅(qū)類
package design; /** * 光驅(qū)類,負(fù)責(zé)從光盤中讀取數(shù)據(jù) */ class CDDriver extends Colleague { //從光盤讀取的原始數(shù)據(jù) private String originData; public CDDriver(Mediator mediator) { super(mediator); } public String getOriginData() { return originData; } /** * 讀取光盤數(shù)據(jù),一旦讀取到數(shù)據(jù),就要通知中介者對象數(shù)據(jù)已經(jīng)準(zhǔn)備好了 */ public void readCD(String originData) { this.originData = originData; //通知中介對象,自己的狀態(tài)發(fā)生了改變 getMediator().changed(this); } }
CPU類
package design; /** * CPU類,負(fù)責(zé)將原始數(shù)據(jù)分離成音頻和視頻 */ public class CPU extends Colleague { //聲音數(shù)據(jù) private String soundData; //視頻數(shù)據(jù) private String videoData; public CPU(Mediator mediator) { super(mediator); } public String getSoundData() { return soundData; } public String getVideoData() { return videoData; } /** * 將數(shù)據(jù)分離,同時通知中介者對象,數(shù)據(jù)已經(jīng)分離 * @param originData */ public void sperateData(String originData) { this.soundData = originData.split(",")[1]; this.videoData = originData.split(",")[0]; //通知中介對象,自己的狀態(tài)發(fā)生了改變 getMediator().changed(this); } }
顯卡類,播放視頻
package design; /** * 顯卡類,播放視頻 */ public class Video extends Colleague { public Video(Mediator mediator) { super(mediator); } public void showVideo(String videoData) { System.out.println("正在觀看:" + videoData); } }
聲卡類
package design; /** * 聲卡類,播放聲音 */ public class Sound extends Colleague { public Sound(Mediator mediator) { super(mediator); } public void showSound(String soundData) { System.out.println("解說:" + soundData); } }
主板類
package design; /** * 主板類,實(shí)現(xiàn)中介者 */ public class MainBoard implements Mediator { private CDDriver cd; private CPU cpu; private Video vc; private Sound sc; public void setCDDriver(CDDriver instance) { this.cd = instance; } public void setCPU(CPU instance) { this.cpu = instance; } public void setVideoCard(Video instance) { this.vc = instance; } public void setSoundCard(Sound instance) { this.sc = instance; } /** * 當(dāng)同時對象自身狀態(tài)發(fā)生改變時,調(diào)用此方法通知中介者對象 * 中介者對象在進(jìn)行邏輯控制,與其他同對象交互 */ public void changed(Colleague obj) { //如果是光驅(qū)類,需要通知CPU去分離數(shù)據(jù) if(obj instanceof CDDriver) { String originData = ((CDDriver) obj).getOriginData(); this.cpu.sperateData(originData); }else if(obj instanceof CPU){//如果是CPU類,需要通知聲卡和顯卡去播放 String videoData = ((CPU) obj).getVideoData(); String soundData = ((CPU) obj).getSoundData(); this.vc.showVideo(videoData); this.sc.showSound(soundData); } } }
客戶端
package design; /** * 客戶端 */ public class Client { public static void main(String[] args) { Mediator mediator = new MainBoard(); CDDriver cd = new CDDriver(mediator); CPU cpu = new CPU(mediator); Video vc = new Video(mediator); Sound sc = new Sound(mediator); mediator.setCDDriver(cd); mediator.setCPU(cpu); mediator.setSoundCard(sc); mediator.setVideoCard(vc); //光驅(qū)讀數(shù)據(jù),通知中介者,中介者通知CPU去分離數(shù)據(jù),CPU分離數(shù)據(jù)完成,通知中介者,中介者通知聲卡和顯卡播放 cd.readCD("終結(jié)者,終結(jié)者音頻"); } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67407.html
摘要:寫在前面作為常年與服務(wù)器打交道的后端開發(fā),基本的操作是一定要運(yùn)用非常熟練的本篇文章就記錄了一些日常工作中最常用的的指令,希望能和大家共同學(xué)習(xí)共同進(jìn)步一與的區(qū)別是的升級版本,它兼容的所有指令,并提供一些新特性,如以不同顏色標(biāo)識語法等之后會總結(jié) 寫在前面:作為常年與服務(wù)器、Linux打交道的后端開發(fā)RD,基本的vi操作是一定要運(yùn)用非常熟練的;本篇文章就記錄了一些日常工作中最常用的的指令,希...
摘要:命令模式需要先輸入冒號,才會進(jìn)入。上下左右左右下上下一個詞,上一個詞常用下一個詞。如果要取消這種縮進(jìn)的話,就要進(jìn)入到粘貼模式記得在這個模式下,無法使用命令來快速打開文件。 Vim三種模式:(重要) 導(dǎo)航(navigation)模式: 這時候,字母就是上下左右鍵。輸入模式:你按字母鍵,才會輸入字母。命令模式:需要先輸入: 冒號,才會進(jìn)入。例如,你輸入 :ls , 就相當(dāng)于運(yùn)行了 ls...
摘要:單例模式單例對象是一種常用的設(shè)計模式。使用代理模式,可以將功能劃分的更加清晰,有助于后期維護(hù)代碼如下這幾種都是比較常用的設(shè)計模式,更多設(shè)計模式后期會繼續(xù)添加。 說起設(shè)計模式,很多編程語言的設(shè)計模式大同小異,而且設(shè)計模式很多,這里就介紹一下java的幾種常見的設(shè)計模式,其實(shí)設(shè)計模式就是一個軟件的設(shè)計思想,從大型軟件架構(gòu)出發(fā),為了升級和維護(hù)方便,所以要降低依賴,降低耦合。先說下設(shè)計模式原則...
閱讀 961·2019-08-30 14:24
閱讀 999·2019-08-30 14:13
閱讀 1807·2019-08-29 17:21
閱讀 2694·2019-08-29 13:44
閱讀 1667·2019-08-29 11:04
閱讀 453·2019-08-26 10:44
閱讀 2573·2019-08-23 14:04
閱讀 916·2019-08-23 12:08