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