【JAVA設計模式】外觀模式(Facade Pattern)
阿新 • • 發佈:2017-08-05
簡單 產生 creat ide oid dsm ref 功能 .net
同理。C模塊也是如此,篇幅原因。這裏不貼代碼了,須要代碼能夠從我github下clone,文末會給出地址。
client調用例如以下:
一 定義
為子系統中的一組接口提供一個一致的界面。Facade模式定義了一個高層的接口,這個接口使得這一子系統更加easy使用。二 案例
一個子系統中擁有3個模塊。每一個模塊中都有3個方法。當中一個為client調用方法,其它兩個則為各子模塊間互相調用方法。此時有例如以下需求,client為完畢功能。須要組合3個模塊中的方法才幹實現功能。三 未使用模式情況
/** * @Description A模塊 * @author jerry * @date 2016年4月11日下午2:16:04 */ public interface AModuleApi { public void a1(); //此方法主要用於外部調用 public void a2(); //下面雙方法主要用於子系統內部間調用 public void a3(); }
/** * @Description A模塊實現 * @author jerry * @date 2016年4月11日下午2:17:10 */ public class AModuleImpl implements AModuleApi { @Override public void a1() { System.out.println("調用了A模塊"); } @Override public void a2() { //TODO 主要用於子模塊間互相調用 } @Override public void a3() { //TODO 主要用於子模塊間互相調用 } }
/** * @Description B模塊 * @author jerry * @date 2016年4月11日下午2:16:12 */ public interface BModuleApi { public void b1(); //此方法主要用於外部調用 public void b2(); //下面雙方法主要用於子系統內部間調用 public void b3(); }
/** * @Description B模塊實現 * @author jerry * @date 2016年4月11日下午2:17:10 */ public class BModuleImpl implements BModuleApi { @Override public void b1() { System.out.println("調用了B模塊"); } @Override public void b2() { //TODO 主要用於子模塊間互相調用 } @Override public void b3() { //TODO 主要用於子模塊間互相調用 } }
public class Client { public static void main(String[] args) { AModuleApi a = new AModuleImpl(); a.a1(); BModuleApi b = new BModuleImpl(); b.b1(); CModuleApi c = new CModuleImpl(); c.c1(); } }相信非常easy能夠寫出這種代碼。
細致想想能夠發現,假設這樣寫。會存在例如以下問題:
- 代碼耦合度太高,client與子系統中各模塊都有關聯。一旦子系統有什麽更改,會涉及到client的改動。
- 對client學習成本太高。client須要學習各個模塊中每一個public方法。知道其什麽含義後才幹進行調用。
四 使用模式的情況
我們能夠在系統這端(即外觀模式屬於系統這端,若屬於客戶這端。仍然須要客戶去了解每一個模塊每一個方法意義,這樣無不論什麽意義。) 加入一個外觀類,由外觀類重組須要調用的方法,例如以下所看到的:/** * @Description 外觀類,通常設計成單例 * @author jerry * @date 2016年4月11日下午2:43:26 */ public class Facade { private Facade(){} public static void test(){ AModuleApi a = new AModuleImpl(); a.a1(); BModuleApi b = new BModuleImpl(); b.b1(); CModuleApi c = new CModuleImpl(); c.c1(); } }
public class Client { public static void main(String[] args) { // AModuleApi a = new AModuleImpl(); // a.a1(); // BModuleApi b = new BModuleImpl(); // b.b1(); // CModuleApi c = new CModuleImpl(); // c.c1(); Facade.test(); } }這樣一來。client僅僅要與外觀類打交道就可以,從而更好地實現了client和子系統各模塊的耦合性。
使用外觀的目的: 不是給子系統加入新的功能接口,而是讓外部降低對子系統內部多個模塊的直接交互。松散耦合,從而可以讓外部更簡單地使用子系統。
當然有時你會有這種需求,client可能僅僅須要調用兩個模塊就可以,那麽現有的外觀模式就無法使用了,僅僅好繞開外觀類。直接找各模塊進行調用。此外,你是否發現。我的ABC模塊裏面除了有供外部調用的方法外。還有各模塊間互相調用的方法,這些方法本不須要client了解。暴露了過多內部細節。會讓client產生疑惑,這就是“接口汙染”
。要解決問題,我們能夠將Facade類定義為接口,並對事實上現,使用工廠模式對其創建實例,例如以下所看到的:
public interface FacadeApi { public void a1(); public void b1(); public void c1(); /** * @Description 原有方法,將各模塊方法組合調用 * @return void * @throws */ public void test(); }
/** * @Description 外觀接口實現 * @author jerry * @date 2016年4月11日下午3:19:25 */ public class FacadeImpl implements FacadeApi { @Override public void a1() { new AModuleImpl().a1(); } @Override public void b1() { new BModuleImpl().b1(); } @Override public void c1() { new CModuleImpl().c1(); } @Override public void test() { a1(); b1(); c1(); } }
/** * @Description 外觀接口實現 * @author jerry * @date 2016年4月11日下午3:19:25 */ public class FacadeImpl implements FacadeApi { @Override public void a1() { new AModuleImpl().a1(); } @Override public void b1() { new BModuleImpl().b1(); } @Override public void c1() { new CModuleImpl().c1(); } @Override public void test() { a1(); b1(); c1(); } }
public class Client { public static void main(String[] args) { // AModuleApi a = new AModuleImpl(); // a.a1(); // BModuleApi b = new BModuleImpl(); // b.b1(); // CModuleApi c = new CModuleImpl(); // c.c1(); // Facade.test(); FacadeApi api = Factory.createFacade(); api.test(); } }這樣以後,就對client降低了模塊內部方法的暴露。
五 總結
外觀模式的本質:封裝交互。簡化調用 何時使用外觀模式:- 假設你希望為一個復雜的子系統提供一個簡單接口
- 假設構建多層結構的系統。能夠考慮使用外觀模式,使用外觀對象作為每層的入口,這樣能夠簡化層間調用,能夠減少耦合度。
Reference:《研磨設計模式》
【JAVA設計模式】外觀模式(Facade Pattern)