門面模式

門面模式的定義

門面模式(Facade Pattern)也叫做外觀模式,是一種比較常用的封裝模式,其定義如

下:

Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level

interface that makes the subsystem easier to use.(要求一個子系統的外部與其內部的通信必須通

過一個統一的對象進行。門面模式提供一個高層次的接口,使得子系統更易于使用。)

門面模式注重“統一的對象”,也就是提供一個訪問子系統的接口,除了這個接口不允許

有任何訪問子系統的行為發生

?

● Facade門面角色

?

客戶端可以調用這個角色的方法。此角色知曉子系統的所有功能和責任。一般情況下,

?

本角色會將所有從客戶端發來的請求委派到相應的子系統去,也就說該角色沒有實際的業務

?

邏輯,只是一個委托類。

?

?

?

● subsystem子系統角色

?

可以同時有一個或者多個子系統。每一個子系統都不是一個單獨的類,而是一個類的集

?

合。子系統并不知道門面的存在。對于子系統而言,門面僅僅是另外一個客戶端而已。

?

?子系統

?

public class ClassA {

?

?????public void doSomethingA(){

?

?????????????//業務邏輯

?

?????}

?

}

?

public class ClassB {

?

?????

?

?????public void doSomethingB(){

?

?????????????//業務邏輯

?

?????}

?

}

?

public class ClassC {

?

?????

?

?????public void doSomethingC(){

?

?????????????//業務邏輯

?

?????}

?

}

門面對象

public class Facade {

?????//被委托的對象

?????private ClassA a = new ClassA();

?????private ClassB b = new ClassB();

?????private ClassC c = new ClassC();

?????//提供給外部訪問的方法

?????public void methodA(){

?????????????this.a.doSomethingA();

?????}

?????

?????public void methodB(){

?

?????????????this.b.doSomethingB();

?????}

?????

?????public void methodC(){

?????????????this.c.doSomethingC();

?????}

}

?

門面模式的優點

門面模式有如下優點。

● 減少系統的相互依賴

如果我們不使用門面模式,外界訪問直接深入到子系統內部,相互之間是一種

強耦合關系,你死我就死,你活我才能活,這樣的強依賴是系統設計所不能接受的,門面模

式的出現就很好地解決了該問題,所有的依賴都是對門面對象的依賴,與子系統無關。

● 提高了靈活性

依賴減少了,靈活性自然提高了。不管子系統內部如何變化,只要不影響到門面對象,

任你自由活動。

● 提高安全性

想讓你訪問子系統的哪些業務就開通哪些邏輯,不在門面上開通的方法,你休想訪問

到。

?

門面模式的缺點

?

門面模式最大的缺點就是不符合開閉原則,對修改關閉,對擴展開放

?

門面模式的使用場景

?

● 為一個復雜的模塊或子系統提供一個供外界訪問的接口

?

● 子系統相對獨立——外界對子系統的訪問只要黑箱操作即可

● 預防低水平人員帶來的風險擴散

?

?

門面模式的注意事項

?

1 一個子系統可以有多個門面

?

● 門面已經龐大到不能忍受的程度

● 子系統可以提供不同訪問路徑

我們以門面模式的通用源代碼為例。ClassA、ClassB、ClassC是一個子系統的中3個對

象,現在有兩個不同的高層模塊來訪問該子系統,模塊一可以完整的訪問所有業務邏輯,也

就是通用代碼中的Facade類,它是子系統的信任模塊;而模塊二屬于受限訪問對象,只能訪

methodB方法,那該如何處理呢?在這種情況下,就需要建立兩個門面以供不同的高層模

塊來訪問,在原有的通用源碼上增加一個新的門面即可

新增門面

public class Facade2 {

?????//引用原有的門面

?????private Facade facade = new Facade();

?????//對外提供唯一的訪問子系統的方法

?????public void methodB(){

?????????????this.facade.methodB();

?????}

}

增加的門面非常簡單,委托給了已經存在的門面對象Facade進行處理,為什么要使用委

托而不再編寫一個委托到子系統的方法呢?那是因為在面向對象的編程中,盡量保持相同的

代碼只編寫一遍,避免以后到處修改相似代碼的悲劇。

?

2 門面不參與子系統內的業務邏輯

我們

把門面上的methodC上的邏輯修改一下,它必須先調用ClassA的doSomethingA方法,然后再

調用ClassCdoSomethingC方法

?

修改門面

?

public class Facade {

?

?????//被委托的對象

?

?????private ClassA a = new ClassA();

?

?????private ClassB b = new ClassB();

?

?????private ClassC c = new ClassC();

?

?????//提供給外部訪問的方法

?

?????public void methodA(){

?

?????????????this.a.doSomethingA();

?

?????}

?

?????

?

?????public void methodB(){

?

?????????????this.b.doSomethingB();

?

?????}

?

?????

?

?????public void methodC(){

?

?????????????this.a.doSomethingA();

?

?????????????this.c.doSomethingC();

?

?????}

?

}

這樣設計是非常不靠譜的,為什么呢?因為你已經讓門面對象參與了業務邏輯,門

面對象只是提供一個訪問子系統的一個路徑而已,它不應該也不能參與具體的業務邏輯,否

則就會產生一個倒依賴的問題:子系統必須依賴門面才能被訪問,這是設計上一個嚴重錯

誤,不僅違反了單一職責原則,同時也破壞了系統的封裝性。

說了這么多,那對于這種情況該怎么處理呢?建立一個封裝類,封裝完畢后提供給門面

?

?

?封裝類

?

public class Context {

?

?????//委托處理

?

?????private ClassA a = new ClassA();

?

?????private ClassC c = new ClassC();

?

?????//復雜的計算

?

?????public void complexMethod(){

?

?????????????this.a.doSomethingA();

?

?????????????this.c.doSomethingC();

?

?????}

?

}

?

該封裝類的作用就是產生一個業務規則complexMethod,并且它的生存環境是在子系統

?

內,僅僅依賴兩個相關的對象,門面對象通過對它的訪問完成一個復雜的業務邏輯

?

門面類

?

public class Facade {

?

?????//被委托的對象

?

?????private ClassA a = new ClassA();

?

?????private ClassB b = new ClassB();

?

?????private Context context = new Context();

?

?????//提供給外部訪問的方法

?

?????public void methodA(){

?

?????????????this.a.doSomethingA();

?

?????}

?

?????

?

?????public void methodB(){

?

?????????????this.b.doSomethingB();

?

?????}

?

?????

?

?????public void methodC(){

?

?????????????this.context.complexMethod();

?

?????}

?

}

?

通過這樣一次封裝后,門面對象又不參與業務邏輯了,在門面模式中,門面角色應該是

?

穩定,它不應該經常變化,一個系統一旦投入運行它就不應該被改變,它是一個系統對外的

?

接口,你變來變去還怎么保證其他模塊的穩定運行呢?但是,業務邏輯是會經常變化的,我

?

們已經把它的變化封裝在子系統內部,無論你如何變化,對外界的訪問者來說,都還是同一

?

個門面,同樣的方法——這才是架構師最希望看到的結構。

?

轉載于:https://www.cnblogs.com/future-zmy/p/6295133.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371651.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371651.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371651.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mysql數據庫申請

前段時間大部門下新成立了一個推廣百度OCR、文字識別、圖像識別等科技能力在金融領域應用的子部門。因為部門剛成立,基礎設施和人力都是欠缺的。當時分到我們部門的任務是抽調一個人做新部門主站前端開發工作。本來說的是只負責頁面的開發工作。當我參加過需求品審會…

Spring–添加SpringMVC –第2部分

在上一部分中,我們為經理和員工實現了控制器。 既然我們知道了解決方法,我們將做很少(但僅做很少)更復雜的事情–任務和時間表的控制器。 因此,讓我們從org.timesheet.web開始。 TaskController 。 首先創建一個類&…

php 正則分隔_探討PHP函數split()如何使用正則表達式切割字符串

對于初學者來說,掌握PHP中常用函數的用法,是其繼續學習的基礎。今天我們就為大家詳細介紹有關PHP函數split()的一些使用方法,希望大家能通過這篇文章介紹的內容增加自己的知識庫。說明array split ( string $pattern, string $string [, int …

通用的ProtostuffSerializer for Java

以前使用 protobuf或protostuff的時候覺得很麻煩,每個類都要單獨定制,于是封裝了一個類。 同事測試過,性能和壓縮率都很好,尤其是相比json的序列化。 需注意:只支持Pojo類(即需要有get/set方法)…

SAS筆記(6) PROC MEANS和PROC FREQ

PROC MEANS和PRC FREQ在做描述性分析的時候很常用,用法也比較簡單,不過這兩個過程步的某些選項容易忘記,本文就梳理一下。 在進入正文前,我們先創建所需的數據集TEST_SCORES: DATA TEST_SCORES; INPUT COUNTY : $9. SC…

休眠:保存vs持久并保存或更新

save和saveOrUpdate之間的區別是什么或save和persist之間的區別是任何Hibernate面試中常見的面試問題,就像Hibernate中get和load方法之間的區別一樣。 Hibernate Session類提供了幾種通過save , saveOrUpdate和persist等方法將對象保存到數據庫中的方法。…

php搜索數據庫設計,PHP數據庫搜索功能設計

其實搜索功能的設計很簡單,幾行代碼就可以完成。下面是form表單。從表單發出的數據名為search,然后發送到../admin/article_SearchResult.php這個文件處理。下面講下article_SearchResult.php這個文件如何實現搜索。$searchs $_POST[‘search‘];?>…

2016 Android Top 10 Library

過去的 2016 年,開源社區異常活躍,很多個人與公司爭相開源自己的項目,讓人眼花繚亂,然而有些項目只是曇花一現,有些項目卻持久創造價值,為開發者提供了極大的便利,這些終究由時間來判斷。今天&a…

集成JavaFX和Swing

我剛剛完成了對使用Swing的應用程序組件的重寫,現在正在使用JavaFX,最后得到了與更大的swing應用程序集成的JavaFX組件。 這是一個很大的應用程序,重寫花了我一段時間,最后一切都很好,我很高興自己做到了。 您可能想在…

提示錯誤:“應為“providerInvariantName”參數的非空字符串。”

我在調試Petapoco的T4模版的時候&#xff0c;鏈接一直報如題那個錯誤。在定性問題為配置文件后找的原因如下&#xff1a; <connectionStrings><add name"這個不行" connectionString"Data Sourcexxx;Initial Catalog數據庫名;User ID帳號;Password密碼…

php oop面試題,PHP面試題 - 對面向對象的理解

具體的題目應該是&#xff1a;什么是面向對象&#xff1f;主要的特征是什么&#xff1f;當然還有很多類似的題目&#xff0c;如果你說一下你對面向對象的理解&#xff0c;或者是你對比一下面向過程等等&#xff0c;諸如此類吧&#xff1f;如果我來回答這個問題&#xff0c;我會…

NOIP2014自測(晚自習兩節+上午兩節 共5個小時)

昨天剛剛考完試然后就翹晚自習跟今天上午兩節課的語文和英語做做noip2014的題目。然后去評測了一番。首先day1day2的t1基本都是模擬&#xff0c;一看就出思路那種&#xff0c;直接ac掉。代碼如下 day1t1&#xff1a;#include<iostream>#define maxn 209using namespace s…

您在eXo平臺上的第一個Juzu Portlet

菊珠是佛教的佛珠。 一句話&#xff0c;我相信您已經學到了什么&#xff0c;印象深刻嗎&#xff1f; 好的&#xff0c;我在這里不談論佛教。 Juzu還是一個用于快速開發Portlet&#xff08;以及即將推出的獨立應用程序&#xff09;的新框架。 您可以在Juzu網站上找到所需的所有…

Spring注入方式及注解配置

一&#xff1a;基于xml的DI&#xff08;Dependency Injection&#xff09; 注入類型&#xff1a; 定義學生Student實體類和小汽車Car實體類&#xff1a;進行封裝和生成ToString(),并自定義屬性Car Student 123456789101112131415161718192021222324252627282930313233343536373…

java 切面 不執行,解決springboot的aop切面不起作用問題(失效的排查)

檢查下springboot的啟動類是否開啟掃描springbootapplicationcomponentscan(basepackages {"com.zhangpu.springboot"})另外springboot默認開啟的enableaspectjautoproxy為true如果不放心可以增加&#xff1a;enableaspectjautoproxy(proxytargetclasstrue)第二種可…

修改readonly屬性的值

一般情況下&#xff0c;readonly屬性的值是無法修改的&#xff0c;但可以通過特殊方式修改。定義一個student的類&#xff0c;其中name屬性為readonly類型的變量 interface JFStudent : NSObjectproperty(nonatomic,copy,readonly) NSString *hisName;property(nonatomic,copy)…

VisualVM:通過SSH監視遠程JVM(是否為JMX)

VisualVM是用于監視JVM&#xff08;5.0&#xff09;的有關內存使用情況&#xff0c;線程&#xff0c;GC&#xff0c;MBeans等的出色工具。讓我們看看如何通過SSH使用它來監視&#xff08;甚至使用JMX對其進行采樣&#xff0c;對帶有JMX的遠程JVM進行監視&#xff09;它。 這篇文…

h5 php js實驗總結,H5學習_番外篇_PHP數據庫操作

1. 文件操作1.1 打開關閉文件fopen()resource fopen ( string filename, string mode [, bool use_include_path [, resource zcontext]] )?fopen()函數將resource綁定到一個流或句柄。綁定之后&#xff0c;腳本就可以通過句柄與此資源交互;例1:以只讀方式打開一個位于本地服務…

ReactNative開發環境

此內容根據徐贏老師的文檔整理后寫處 原版地址&#xff1a;https://tuomaxu.gitbooks.io/reactnative/content/ ReactNative是跨平開發的解決方案&#xff0c;在開發平臺的選擇上&#xff0c;mac平臺和win平臺都可以。 所需要工具如下&#xff1a; 1&#xff0c;Nodejs環境 2&a…

Python自動化開發 - 字符串, 列表, 元組, 字典和和文件操作

一、字符串特性&#xff1a;字符串本身不可修改&#xff0c;除非字符串變量重新賦值。Python3中所有字符串都是Unicode字符串&#xff0c;支持中文。 >>> name "Jonathan" >>> name "Jonathan" "Ni" >>>print(na…