門面模式
參考資料
大話設(shè)計(jì)模式
設(shè)計(jì)模式之禪
github我見(jiàn)過(guò)最好的設(shè)計(jì)模式
http://c.biancheng.net/view/1326.html
定義
也稱為外觀模式
外觀模式是一種結(jié)構(gòu)型設(shè)計(jì)模式, 能為程序庫(kù)、 框架或其他復(fù)雜類提供一個(gè)簡(jiǎn)單的接口。
- 讓子系統(tǒng)更加容易使用,屬于結(jié)構(gòu)型模式
例子
App訂單接口
- 后臺(tái)提供一個(gè)聚合接口
- 在內(nèi)部分別調(diào)用了訂單,物流,用戶系統(tǒng)
- 能夠節(jié)省前端的請(qǐng)求
適用場(chǎng)景
- 子系統(tǒng)越來(lái)越復(fù)雜,增加門面模式來(lái)提供簡(jiǎn)單接口
- 構(gòu)建多層系統(tǒng)結(jié)構(gòu),利用門面對(duì)象作為每層的入口,簡(jiǎn)化層間調(diào)用
生活中的例子
- 前臺(tái)接待員
- 用來(lái)做向?qū)?/li>
- 包工頭
- 通過(guò)包工頭來(lái)找粉刷匠,找泥工等
通用寫法

image-20210104125544586
物流系統(tǒng)案例

image-20210104125703356
門面業(yè)務(wù)幫我們聚合扣款,監(jiān)測(cè),發(fā)貨的功能,客戶端只需要找門面就行了
源碼中的案例
Spring的JdbcUtils
public static boolean supportsBatchUpdates(Connection con) {
try {
DatabaseMetaData dbmd = con.getMetaData();
if (dbmd != null) {
if (dbmd.supportsBatchUpdates()) {
logger.debug("JDBC driver supports batch updates");
return true;
}
else {
logger.debug("JDBC driver does not support batch updates");
}
}
}
catch (SQLException ex) {
logger.debug("JDBC driver 'supportsBatchUpdates' method threw exception", ex);
}
return false;
}
幫我們包裝了對(duì)連接的操作,這樣客戶端只需要使用JdbcUtils就行了
Mybatis的Configuration
public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
ResultHandler resultHandler, BoundSql boundSql) {
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
return resultSetHandler;
}
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
幫我們創(chuàng)建對(duì)應(yīng)的對(duì)象
和其他設(shè)計(jì)模式的區(qū)別
門面模式和代理的區(qū)別
- 門面模式就是一種特殊的靜態(tài)代理
- 門面模式,重點(diǎn)在于封裝
- 靜態(tài)代理,重點(diǎn)是在增強(qiáng)
不做增強(qiáng)的靜態(tài)代理就是門面模式
門面模式和單例模式的區(qū)別
經(jīng)常把門面模式做成單例模式,工具包
優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 簡(jiǎn)化了調(diào)用過(guò)程,無(wú)需深入了解子系統(tǒng),防止給子系統(tǒng)帶來(lái)風(fēng)險(xiǎn)
- 減少系統(tǒng)依賴,松散耦合
- 更好的劃分訪問(wèn)層次,提高了安全性
- 迪米特法則,最少知道原則
缺點(diǎn)
- 增加子系統(tǒng)和擴(kuò)展子系統(tǒng)行為的時(shí)候,容易帶來(lái)未知風(fēng)險(xiǎn)
- 不符合開(kāi)閉原則
- 某些情況下可能違背單一職責(zé)原則
問(wèn)題
門面模式
想一想什么場(chǎng)景下考慮使用門面模式
- 一個(gè)子系統(tǒng)比較復(fù)雜時(shí),比如算法或者業(yè)務(wù)比較復(fù)雜,就可以封裝出一個(gè)或多個(gè)門面出來(lái),項(xiàng)目的結(jié)構(gòu)簡(jiǎn)單,而且擴(kuò)展性非常好。
- 對(duì)于一個(gè)較大項(xiàng)目,為了避免人員帶來(lái)的風(fēng)險(xiǎn),也可以使用門面模式,技術(shù)水平比較差的成員,盡量安排獨(dú)立的模塊,然后把他寫的程序封裝到一個(gè)門面里,盡量讓其他項(xiàng)目成員不用看到這些人的代碼,看也看不懂,我也遇到過(guò)一個(gè)“高人”寫的代 碼,private方法、構(gòu)造函數(shù)、常量基本都不用,你要一個(gè)public方法, 好,一個(gè)類里就一個(gè)public方法,所有代碼都在里面,然后你就看吧, 一大坨程序,看著就能把人逼瘋。使用門面模式后,對(duì)門面進(jìn)行單元測(cè)試,約束項(xiàng)目成員的代碼質(zhì)量,對(duì)項(xiàng)目整體質(zhì)量的提升也是一個(gè)比較好的幫助。
我的筆記倉(cāng)庫(kù)地址gitee 快來(lái)給我點(diǎn)個(gè)Star吧