目錄
門面模式UML圖" >門面模式UML圖
門面模式中的角色" >門面模式中的角色
門面模式的擴充" >門面模式的擴充
缺点" >缺点
大神们是如何使用的 " >大神们是如何使用的
首頁 Java java教程 工作五年了,居然還不懂 門面模式!

工作五年了,居然還不懂 門面模式!

Aug 28, 2023 pm 03:11 PM
門面模式


好啦,進入我們的主題,今天我給大家分享設計模式中的門面模式用貼切的生活故事,以及真實專案場景來講設計模式,最後用一句話來總結這個設計模式。

故事

#開發的朋友都知道,後端開發通常都是:

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使用者帳戶資訊。

門面模式適用場景

#在軟體系統中,門面模式適用於下列應用情境。

  • 為一個複雜的模組或子系統提供一個簡潔的供外界存取的介面。
  • 希望提高子系統的獨立性時。
  • 當子系統由於不可避免的暫時原因導致可能存在Bug或性能相關問題時,可以透過門面模式提供一個高層接口,隔離客戶端與子系統的直接交互,預防代碼污染。

門面模式通用寫入法

#還是使用程式碼來實作一個簡單的門面模式,因為咱們最喜歡的就是從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圖


工作五年了,居然還不懂 門面模式!

結合這個UML圖,在回顧銀行前台人員和包工頭的案例,就更輕鬆的理解門面模式了。

門面模式中的角色

由上圖可以看到,門面模式主要包含2個角色。

  • 外觀角色(Facade):也叫作門面角色,是系統對外的統一介面。
  • 子系統角色(Service):可以同時有一個或多個Service。每個Service都不是單獨的類,而是一個類別的集合。 Service們並不知道Facade的存在,對Service們而言,Facade 只是另一個客戶端而已(即FacadeServiceAServiceBServiceC透明)。

門面模式的擴充

##● 減少系統的相互依賴 想想看,如果我們不使用門面模式,外界訪問直接深入到子系統內部,相互之間是一種強耦合關係,你死我就死,你活我才能活,這樣的強依賴是系統設計所不能接受的,門面模式的出現就很好地解決了這個問題,所有的依賴都是對門面物件的依賴,與子系統無關。

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

● 提高安全性   想让你访问子系统的哪些业务就开通哪些逻辑,不在门面上开通的方法,你休想访问到 。

缺点

  • 当增加子系统和扩展子系统行为时,可能容易带来未知风险。
  • 不符合开闭原则。
  • 某些情况下,可能违背单一职责原则

大神们是如何使用的

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这一个类就好了,我不用去管ConnectionResultSet等是怎么创建的,需要的时候,我调用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针对ResponseSession也封装了对应的ResponseFacade类和StandardSessionFacade类,感兴趣的小伙伴可以深入了解一下。

PS:基本上所有以Facade结尾的类,都是使用到了门面模式。

參考:tom的設計模式課程

總結

##好了,關於門面模式就分享這麼多,看完本文是不是覺得門面模式其實很簡單的,另外在工作也可以考慮是不是可以把它用上,同時,面試的時候也可以用來吹吹。

以上是工作五年了,居然還不懂 門面模式!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? 使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? Apr 19, 2025 pm 09:51 PM

在使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名以構建查詢條件,是一個常見的難題。本文將針...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

See all articles