Java設(shè)計模式之外觀模式
本文通過老王改造小王公司的整體架構(gòu)來說明外觀模式,所謂的外觀模式其實就是在各種復(fù)雜的子系統(tǒng)中抽象出來一個接口,隱藏具體的實現(xiàn)細(xì)節(jié),調(diào)用方調(diào)用時只需要調(diào)用接口即可。為了加深理解我們會選出外觀模式在源碼中的應(yīng)用進(jìn)行重點的介紹,最后是我對設(shè)計模式學(xué)習(xí)過程中的一些思考。
讀者可以拉取完整代碼到本地進(jìn)行學(xué)習(xí),實現(xiàn)代碼均測試通過后上傳到碼云,本地源碼下載。
一、引出問題
隨著小王創(chuàng)業(yè)的不斷深入,公司各個業(yè)務(wù)模塊越來越復(fù)雜,每當(dāng)客戶們與他的合作時都要深入各個模塊內(nèi)部,而且客戶要依賴小王的各個模塊,給使用模塊的客戶帶來了困難。
小王就想請老王幫他規(guī)劃一下公司的架構(gòu)。
老王聽完了小王的需求,開始給他分析問題。
現(xiàn)在的公司的架構(gòu)已經(jīng)演變的相當(dāng)復(fù)雜了,客戶訪問你的時候都要通過各個子系統(tǒng),你應(yīng)該將你所有的子系統(tǒng)整合到一個前天(接口),客戶訪問你的子系統(tǒng)只需要通過這個前臺(接口)即可。這樣就能很好的解決這個問題。
二、概念與運(yùn)用
老王提出來的解決辦法正是外觀模式,是一種通過為多個復(fù)雜的子系統(tǒng)提供一個一致的接口,而使這些子系統(tǒng)更加容易被訪問的模式。
該模式對外有一個統(tǒng)一接口,外部應(yīng)用程序不用關(guān)心內(nèi)部子系統(tǒng)的具體細(xì)節(jié),這樣會大大降低應(yīng)用程序的復(fù)雜度,提高了程序的可維護(hù)性。
該模式應(yīng)該是包含兩個角色:
①各個子系統(tǒng)角色
②外觀角色
我們接著看其實現(xiàn)代碼:
子系統(tǒng):
/** * @author tcy * @Date 11-08-2022 */ public class SystemWork01 { public void method1() { System.out.println("子系統(tǒng)01的業(yè)務(wù)模式!"); } } /** * @author tcy * @Date 11-08-2022 */ public class SystemWork02 { public void method1() { System.out.println("子系統(tǒng)02的業(yè)務(wù)模式!"); } } /** * @author tcy * @Date 11-08-2022 */ public class SystemWork03 { public void method1() { System.out.println("子系統(tǒng)03的業(yè)務(wù)模式!"); } }
外觀角色:
/** * @author tcy * @Date 11-08-2022 */ public class Facade { private SystemWork01 obj1 = new SystemWork01(); private SystemWork02 obj2 = new SystemWork02(); private SystemWork03 obj3 = new SystemWork03(); public void method() { obj1.method1(); obj2.method1(); obj3.method1(); } }
客戶端:
/** * @author tcy * @Date 11-08-2022 */ public class Client { public static void main(String[] args) { Facade f = new Facade(); f.method(); } }
外觀模式的實現(xiàn)代碼很簡單,讀者想必看一遍就知道什么意思了。但學(xué)會和會用是兩碼事,我們舉一些外觀模式以便讀者在使用時可以參考代碼。
三、應(yīng)用
看似外觀模式很簡單,實際應(yīng)用中應(yīng)該不多,其實在實際應(yīng)用中處處有體現(xiàn),比如Java開發(fā)學(xué)習(xí)的第一個框架肯定就是SSM,而SSM采用分層,而各個層之間的訪問就是外觀模式的體現(xiàn)。
還有就是我們在維護(hù)一個復(fù)雜的系統(tǒng)時,新系統(tǒng)不得不依賴?yán)舷到y(tǒng)的某些功能,那使用外觀模式是最合適不過的。
在Mybatis的Configuration就是使用的外觀模式。
客戶端使用Mybatis的功能時,只需要調(diào)用Configuration的功能即可。
我們簡單看下Configuration的源碼。
//Configuration 類: public class Configuration { protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory(); protected ObjectFactory objectFactory = new DefaultObjectFactory(); protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory(); public MetaObject newMetaObject(Object object) { return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory); } } //MetaObject類 public class MetaObject { private Object originalObject; private ObjectWrapper objectWrapper; private ObjectFactory objectFactory; private ObjectWrapperFactory objectWrapperFactory; private ReflectorFactory reflectorFactory; public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) { if (object == null) { return SystemMetaObject.NULL_META_OBJECT; } else { return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory); } } private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) { this.originalObject = object; this.objectFactory = objectFactory; this.objectWrapperFactory = objectWrapperFactory; this.reflectorFactory = reflectorFactory; if (object instanceof ObjectWrapper) { this.objectWrapper = (ObjectWrapper) object; } else if (objectWrapperFactory.hasWrapperFor(object)) { this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object); } else if (object instanceof Map) { this.objectWrapper = new MapWrapper(this, (Map) object); } else if (object instanceof Collection) { this.objectWrapper = new CollectionWrapper(this, (Collection) object); } else { this.objectWrapper = new BeanWrapper(this, object); } } }
在使用MetaObject時,客戶端只需要調(diào)用Configuration的newMetaObject(Object object)方法,并傳遞一個Object參數(shù),就可以獲取對應(yīng)的MetaObject。
至于具體的產(chǎn)生什么樣的MetaObject,則有MetaObject的類的forObject(object, objectFactory, objectWrapperFactory, reflectorFactory)方法實現(xiàn)。
具體深究Mybatis 的內(nèi)部實現(xiàn)細(xì)節(jié)還是很麻煩的,這里是淺談一下,有興趣的讀者可以拉Mybatis源碼進(jìn)行重點學(xué)習(xí)。
四、總結(jié)
前幾天在一個技術(shù)公眾號上看到了一個爭論,關(guān)于設(shè)計模式在新手期要不要學(xué)的問題,一些人的觀點就是新手壓根看不懂設(shè)計模式,看懂了實際開發(fā)也不會用。
另外一派的觀點則是,設(shè)計模式一定要學(xué),在你開發(fā)中慢慢訓(xùn)練有意識的使用設(shè)計模式,在你開發(fā)了一段時間的系統(tǒng)后再學(xué)習(xí)設(shè)計模式的話,那時候你壓根沒有時間去重構(gòu)你的代碼。
我的觀點更趨向于后者,自從我學(xué)了設(shè)計模式以后,再寫代碼的時候,尤其是在老代碼之上加一些新功能時,我會下意識的回憶一下學(xué)過的設(shè)計模式,思考使用設(shè)計模式對我的代碼有沒有幫助。
學(xué)過設(shè)計模式以后,在日常開發(fā)中技術(shù)水平不知不覺就提高了,不像以前那樣為了實現(xiàn)功能而實現(xiàn)功能。
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
jquery uploadify和apache Fileupload實現(xiàn)異步上傳文件示例
這篇文章主要介紹了jquery uploadify和apache Fileupload實現(xiàn)異步上傳文件示例,需要的朋友可以參考下2014-05-05關(guān)于Java中的實體類要?implements?Serializable的原因分析
這篇文章主要介紹了Java中的實體類為什么要?implements?Serializable,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06springboot集成swagger3與knife4j的詳細(xì)代碼
這篇文章主要介紹了springboot集成swagger3與knife4j,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08javabean servlet jsp實現(xiàn)分頁功能代碼解析
這篇文章主要為大家詳細(xì)解析了javabean servlet jsp實現(xiàn)分頁功能代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09