好啦,進入我們的主題,今天我給大家分享設計模式中的門面模式
。 用貼切的生活故事,以及真實專案場景來講設計模式
,最後用一句話來總結這個設計模式。
#開發的朋友都知道,後端開發通常都是:
controller---servie---dao/mapper/repository
但是,我問過很多人,熟悉門面模式不?有的工作五年了都不知道。
今天老田,就帶你來看看門面模式。
#門面模式(Facade Pattern
)又叫作外觀模式,提供了一個統一的接口,用來存取子系統中的一群接口。其主要特徵是定義了一個高層接口,讓子系統更容易使用,屬於結構型設計模式。
英文:
Provide a unified interface to a set of interfaces in asubsystem.Facade defines a higher-level interface that makes thesubsystem easier to use.
其實,在日常編碼工作中,我們都在有意無意地大量使用門面模式。但凡只要高層模組需要調度多個子系統(2個以上類對象),我們都會自覺地創建一個新類封裝這些子系統,提供精簡的接口,讓高層模組可以更容易地間接調用這些子系統的功能。
#關於門面模式,在生活中的案例,非常多。
案例1:去銀行辦理業務,有個前台接待你,然後,這個前台會問你需要辦什麼業務,他會一個一個帶你辦理,這樣我們就不需要到處亂串、到處找對應業務視窗了。這個前台人員就相當於門面模式。
案例2:我們蓋房子,如果沒有包工頭的話,那就是你自己要去找水泥工,電工、裝潢工等。但如果有了包工頭,這些活你都不用乾了,直接跟包工頭說,需要電工來把線路搞好。這個包工頭就可以理解為門面模式。
案例3:我們後端開發的controller
,也可以理解為門面模式,比如說獲取用戶帳戶信息,先查UserService
獲取用戶信息,然後查UserAccountService
使用者帳戶資訊。
#在軟體系統中,門面模式適用於下列應用情境。
#還是使用程式碼來實作一個簡單的門面模式,因為咱們最喜歡的就是從demo開始。
業務場景:現在需要呼叫三個service的各自的方法:
public class ServiceA { public void doA(){ System.out.println("do ServiceA"); } } public class ServiceB { public void doB(){ System.out.println("do ServiceB"); } } public class ServiceC { public void doC(){ System.out.println("do ServiceC"); } }
在沒有引入門面模式的時候,客戶端是這麼調用的:
public class Client { public static void main(String[] args) { ServiceA serviceA=new ServiceA(); ServiceB serviceB=new ServiceB(); ServiceC serviceC=new ServiceC(); serviceA.doA(); serviceB.doB(); serviceC.doC(); } }
每次,客戶端自己都需要建立很多service對象,如果涉及到有很多個service,那這程式碼不是很尷尬嗎?會出現大量重複性的程式碼。
運行結果
do ServiceA do ServiceB do ServiceC
下面我們就來加入門面模式
:
public class Facade { //是不是很像我们controller里注入各种service? private ServiceA serviceA = new ServiceA(); private ServiceB serviceB = new ServiceB(); private ServiceC serviceC = new ServiceC(); public void doA() { serviceA.doA(); } public void doB() { serviceB.doB(); } public void doC() { serviceC.doC(); } }
客戶端變成了:
public class Client { public static void main(String[] args) { //轻轻松松的搞定,只需要创建门面这个对象即可 Facade facade=new Facade(); facade.doA(); facade.doB(); facade.doC(); } }
運行結果:
do ServiceA do ServiceB do ServiceC
結合這個UML圖,在回顧銀行前台人員和包工頭的案例,就更輕鬆的理解門面模式了。
由上圖可以看到,門面模式主要包含2個角色。
Facade
):也叫作門面角色,是系統對外的統一介面。 Service
):可以同時有一個或多個Service
。每個Service
都不是單獨的類,而是一個類別的集合。 Service
們並不知道Facade
的存在,對Service們而言,Facade
只是另一個客戶端而已(即Facade
對ServiceA
、ServiceB
、ServiceC
透明)。 ##● 減少系統的相互依賴 想想看,如果我們不使用門面模式,外界訪問直接深入到子系統內部,相互之間是一種強耦合關係,你死我就死,你活我才能活,這樣的強依賴是系統設計所不能接受的,門面模式的出現就很好地解決了這個問題,所有的依賴都是對門面物件的依賴,與子系統無關。
###● 提高了靈活性 依賴減少了,靈活性自然提高了。不管子系統內部如何變化,只要不影響門面對象,任你自由活動。 ###● 提高安全性 想让你访问子系统的哪些业务就开通哪些逻辑,不在门面上开通的方法,你休想访问到 。
违背单一职责原则
。在Spring
中也是有大量使用到门面模式,比如说
org.springframework.jdbc.support.JdbcUtils
再来看看其中的方法
public static void closeConnection(@Nullable Connection con) { con.close(); } public static Object extractDatabaseMetaData(DataSource dataSource, DatabaseMetaDataCallback action) throws MetaDataAccessException { Connection con = null; try { con = DataSourceUtils.getConnection(dataSource); DatabaseMetaData metaData = con.getMetaData(); if (metaData == null) { //..... } return action.processMetaData(metaData); } } ......
都是给我封装好了方法,对于我们开发者来说,我只面向JdbcUtils
这一个类就好了,我不用去管Connection
、ResultSet
等是怎么创建的,需要的时候,我调用JdbcUtils
的对应方法即可获得对应的对象。
在Mybatis
中也是用到了门面模式,比如:
org.apache.ibatis.session.Configuration
在Configuration
中以new
开头的方法,比如:
public Executor newExecutor(Transaction transaction) { return newExecutor(transaction, defaultExecutorType); } public MetaObject newMetaObject(Object object) { return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory); } public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { ... return parameterHandler; } public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql) { ... return resultSetHandler; } public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement){ ... }
对于调用这些方法的地方,他并不知道是怎么new
出来的对象,只管使用就行了。
在Tomcat
中也有门面模式,比如:
org.apache.catalina.connector.RequestFacade
从名字就知道它用了门面模式。它封装了非常多的request
操作,也整合了很多servlet-api
以外的内容,给用户使用提供了很大便捷。同样,Tomcat
针对Response
和Session
也封装了对应的ResponseFacade
类和StandardSessionFacade
类,感兴趣的小伙伴可以深入了解一下。
PS
:基本上所有以Facade
结尾的类,都是使用到了门面模式。
參考:tom的設計模式課程
以上是工作五年了,居然還不懂 門面模式!的詳細內容。更多資訊請關注PHP中文網其他相關文章!