上??娝乖O計公司官網(wǎng)windows11優(yōu)化大師
前言
什么是門面模式
門面模式是一種結(jié)構(gòu)型設計模式,它提供了一個統(tǒng)一的接口,用來訪問子系統(tǒng)中的一群接口。它定義了一個高層接口,讓子系統(tǒng)更容易使用。這種模式常用于將一個復雜的子系統(tǒng)封裝成一個簡單的接口,使得客戶端可以方便地使用子系統(tǒng)的功能,而不需要了解子系統(tǒng)的具體實現(xiàn)細節(jié)。
門面模式的特點
- 代理模式能夠隱藏真實對象的實現(xiàn)細節(jié),使客戶端無需知曉真實對象的工作方式和結(jié)構(gòu)。
- 通過代理類來間接訪問真實類,可以在不修改真實類的情況下對其進行擴展、優(yōu)化或添加安全措施。
- 代理模式實現(xiàn)起來簡單,易于擴展和維護,符合面向?qū)ο笤O計原則中的開閉原則。
門面模式的核心角色
門面模式(Facade Pattern)有三個核心角色:
- 門面角色(Facade):這是門面模式的核心,被客戶角色調(diào)用。它熟悉子系統(tǒng)的功能,內(nèi)部根據(jù)客戶角色已有的需求預定了幾種功能組合。
- 子系統(tǒng)角色(Subsystem):實現(xiàn)了子系統(tǒng)的功能。對于子系統(tǒng)角色來說,門面角色和客戶角色都是未知的,它沒有任何門面角色信息和鏈接。
- 客戶角色(Client):這是使用門面模式的外部請求者,它通過門面角色來訪問子系統(tǒng),以獲取所需的功能。
門面模式如何實現(xiàn)
假如用門面模式來模擬實現(xiàn)一下去飯店點菜吃飯應該怎么實現(xiàn)呢?雖然去飯店吃飯這件事挺普通的,但是要想吃到飯,起碼是要走這樣一個流程:點餐、炒菜、上菜、收/付錢。其實這里的飯店就可以看作是一個門面角色,飯店內(nèi)不同的角色:如老板、收銀員、服務員、廚師等,可以看作是飯店這個門面內(nèi)的子系統(tǒng)角色,不同的角色職責是不同的,服務員負責幫客人點餐、上菜,廚師炒菜,收銀員負責收錢,但是對于客人而言,吃飯是重點,通常不會關注是誰做的、誰端上來的。
那使用門面模式怎么實現(xiàn)呢?UML類圖如下:
1、Restaurant:飯店類,有三個List類型的屬性,分別用來表示飯店內(nèi)會有廚師、服務員、收銀員等不同角色的人員對象;對應還有三個可以給飯店增加三種不同角色人員的方法;最后一個方法就是飯店對外的主要職能:可以吃飯;
2、Waiter:服務員類,有兩個方法:幫客人下單、上菜;
3、Cook:廚師類,有一個方法:炒菜;
4、Cashier:收銀員類,有一個方法:收菜;
5、Cilent:客戶端類,作為客戶端,直接依賴Restaurant類,而不具體去找某個服務員或廚師;
/*** 服務員*/
@Data
@AllArgsConstructor
public class Waiter {private String name;public void placeOrder(){System.out.println(this.name+"->幫客人點菜");}public void serveDishes(){System.out.println(this.name+"->給客人上菜");}
}
/*** 廚師*/
@Data
@AllArgsConstructor
public class Cook {private String name;public void cooking() {System.out.println(this.name + "->炒菜");}
}
/*** 收銀員*/
@Data
@AllArgsConstructor
public class Cashier {private String name;public void collectMoney() {System.out.println(this.name + "->收錢");}
}
/*** 飯店*/@Data
public class Restaurant {private String name;private List<Cook> cooks = new ArrayList<>();private List<Waiter> waiters = new ArrayList<>();private List<Cashier> cashiers = new ArrayList<>();public Restaurant(String name) {this.name = name;}public void addCooks(Cook cook) {this.cooks.add(cook);}public void addWaiter(Waiter waiter) {this.waiters.add(waiter);}public void addCashier(Cashier cashier) {this.cashiers.add(cashier);}private int ranomInt(Integer maxInt){Random random = new Random();return random.nextInt(maxInt);}public void eat(){this.waiters.get(this.ranomInt(this.waiters.size())).placeOrder();//點菜this.cooks.get(this.ranomInt(this.cooks.size())).cooking();//炒菜this.waiters.get(this.ranomInt(this.waiters.size())).serveDishes();//上菜System.out.println("客人->吃飯");this.cashiers.get(this.ranomInt(this.cashiers.size())).collectMoney();//收錢}
}
public class Client {public static void main(String[] args) {Restaurant restaurant = new Restaurant("和平飯店");Cook cook1 = new Cook("張廚師");Cook cook2 = new Cook("李廚師");restaurant.addCooks(cook1);restaurant.addCooks(cook2);Waiter waiter1 = new Waiter("王小紅");Waiter waiter2 = new Waiter("張小月");restaurant.addWaiter(waiter1);restaurant.addWaiter(waiter2);Cashier cashier1 = new Cashier("老板");Cashier cashier2 = new Cashier("老板娘");restaurant.addCashier(cashier1);restaurant.addCashier(cashier2);restaurant.eat();}
}
門面模式的適用場景
門面模式適用于以下場景:
- 為一個復雜的子系統(tǒng)提供一個簡單的接口,使得客戶端可以方便地使用子系統(tǒng)的功能。
- 需要對一個子系統(tǒng)進行封裝,并隱藏子系統(tǒng)的內(nèi)部實現(xiàn)細節(jié),只提供一個精簡的接口供客戶端使用,這樣可以降低客戶端與子系統(tǒng)的耦合度。
- 需要提高子系統(tǒng)的獨立性,使得客戶端不直接與子系統(tǒng)交互,而是通過門面角色來進行交互。
- 需要隔離客戶端與子系統(tǒng)的直接交互,預防低水平人員帶來的風險擴散。
總結(jié)
優(yōu)點:
- 減少系統(tǒng)的相互依賴:門面模式可以讓客戶端只需要依賴門面對象,而與子系統(tǒng)無關。這樣可以降低系統(tǒng)耦合度。
- 提高靈活性:通過門面角色,客戶端不再直接與子系統(tǒng)交互,而是通過門面角色提供的精簡接口來實現(xiàn)交互。這樣,子系統(tǒng)的內(nèi)部實現(xiàn)細節(jié)可以被隱藏起來,子系統(tǒng)如何變化對客戶端來說是透明的,提高了系統(tǒng)的靈活性。
- 提高安全性:外部只能通過門面訪問子系統(tǒng)的功能,門面沒有開放的就不能訪問,提高了子系統(tǒng)的安全性。
缺點:
- 不符合開閉原則。系統(tǒng)投產(chǎn)后,一旦發(fā)現(xiàn)錯誤,只能修改門面角色的代碼,風險比較大。
- 系統(tǒng)的復雜性和理解難度有一定增加;
總的來說,門面模式可以簡化復雜子系統(tǒng)的使用、隱藏實現(xiàn)細節(jié)、提高子系統(tǒng)獨立性和隔離客戶端與子系統(tǒng)的直接交互,但也存在一些缺點需要注意。在具體使用時,需要根據(jù)具體情況進行權(quán)衡,并考慮是否適合使用該模式。