外觀模式是一種結(jié)構(gòu)類型的代碼設(shè)計(jì)模式之一缺虐,其目的是提供一個(gè)簡(jiǎn)單的接口或門(mén)面(客戶端視角的“外觀”)芜壁,使復(fù)雜的子系統(tǒng)或類更易于使用。它通過(guò)封裝子系統(tǒng)中的一組接口志笼,并提供一個(gè)統(tǒng)一的接口,簡(jiǎn)化了對(duì)子系統(tǒng)的操作把篓。
模式實(shí)例代碼
使用Go語(yǔ)言實(shí)現(xiàn)外觀模式的示例代碼:
package main
import "fmt"
// SubsystemA 是子系統(tǒng)A
type SubsystemA struct{}
func (s *SubsystemA) MethodA() {
fmt.Println("SubsystemA: MethodA")
}
// SubsystemB 是子系統(tǒng)B
type SubsystemB struct{}
func (s *SubsystemB) MethodB() {
fmt.Println("SubsystemB: MethodB")
}
// Facade 是外觀
type Facade struct {
subsystemA *SubsystemA
subsystemB *SubsystemB
}
func NewFacade() *Facade {
return &Facade{
subsystemA: &SubsystemA{},
subsystemB: &SubsystemB{},
}
}
// Execute 執(zhí)行操作
func (f *Facade) Execute() {
f.subsystemA.MethodA()
f.subsystemB.MethodB()
}
func main() {
facade := NewFacade()
facade.Execute()
}
上述代碼中纫溃,SubsystemA和SubsystemB是兩個(gè)子系統(tǒng),它們分別實(shí)現(xiàn)了不同的方法韧掩。Facade是外觀紊浩,它封裝了SubsystemA和SubsystemB,提供了一個(gè)統(tǒng)一的接口Execute()來(lái)執(zhí)行操作。通過(guò)外觀模式坊谁,客戶端只需與外觀對(duì)象交互费彼,而無(wú)需直接與子系統(tǒng)進(jìn)行交互,從而簡(jiǎn)化了操作的復(fù)雜性口芍。在示例代碼中箍铲,客戶端只需要?jiǎng)?chuàng)建外觀對(duì)象并調(diào)用Execute()方法即可完成操作。
外觀模式代碼擴(kuò)展性
考慮到代碼的未來(lái)的擴(kuò)展性鬓椭,外觀對(duì)象本身通常是保持不變的颠猴,不應(yīng)該隨著子系統(tǒng)的變化而頻繁修改。外觀模式充當(dāng)了客戶端和子系統(tǒng)之間的中介小染,隱藏了子系統(tǒng)的復(fù)雜性翘瓮,客戶端只需與外觀對(duì)象進(jìn)行交互。
如果后續(xù)需要擴(kuò)展或修改子系統(tǒng)中的某個(gè)部分裤翩,可以通過(guò)以下方式來(lái)實(shí)現(xiàn):
- 添加新的子系統(tǒng):如果需要添加新的功能或子系統(tǒng)资盅,可以創(chuàng)建一個(gè)新的子系統(tǒng),并在外觀對(duì)象中添加相應(yīng)的方法踊赠,將新的子系統(tǒng)集成到外觀中呵扛。這樣客戶端仍然只需要與外觀對(duì)象進(jìn)行交互,而不需要關(guān)心新的子系統(tǒng)的具體實(shí)現(xiàn)臼疫。
- 修改子系統(tǒng)的行為:如果需要修改子系統(tǒng)的行為择份,可以直接在子系統(tǒng)內(nèi)部進(jìn)行修改,而不會(huì)影響外觀對(duì)象或客戶端的代碼烫堤。外觀對(duì)象僅僅是對(duì)子系統(tǒng)的調(diào)用進(jìn)行封裝荣赶,修改子系統(tǒng)的行為不會(huì)改變外觀對(duì)象的接口。
- 繼承和重寫(xiě):可以通過(guò)繼承外觀對(duì)象的方式來(lái)擴(kuò)展或修改外觀對(duì)象的行為鸽斟。通過(guò)創(chuàng)建一個(gè)新的子類拔创,并重寫(xiě)需要修改的方法,可以實(shí)現(xiàn)對(duì)外觀對(duì)象行為的定制富蓄。這種方式可以支持對(duì)外觀對(duì)象的擴(kuò)展和靈活性剩燥。
總之,通過(guò)保持外觀對(duì)象的穩(wěn)定性和封裝性立倍,可以更容易地?cái)U(kuò)展和修改子系統(tǒng)灭红,同時(shí)確保客戶端的代碼不需要修改口注。
比如未來(lái)需要添加新的子系統(tǒng)C時(shí)变擒,可以按照以下步驟對(duì)外觀模式進(jìn)行擴(kuò)展:
首先,在現(xiàn)有的代碼基礎(chǔ)上創(chuàng)建一個(gè)新的子系統(tǒng)C:
// 新增子系統(tǒng)C
type SubsystemC struct{}
func (s *SubsystemC) MethodC() {
fmt.Println("SubsystemC: MethodC")
}
然后寝志,在外觀對(duì)象中添加對(duì)子系統(tǒng)C的集成和方法調(diào)用:
// Facade 是外觀
type Facade struct {
subsystemA *SubsystemA
subsystemB *SubsystemB
subsystemC *SubsystemC //擴(kuò)展
}
func NewFacade() *Facade {
return &Facade{
subsystemA: &SubsystemA{},
subsystemB: &SubsystemB{},
subsystemC: &SubsystemC{}, //擴(kuò)展
}
}
// Execute 執(zhí)行操作
func (f *Facade) Execute() {
f.subsystemA.MethodA()
f.subsystemB.MethodB()
f.subsystemC.MethodC() //擴(kuò)展
}
現(xiàn)在娇斑,外觀對(duì)象就包含了子系統(tǒng)C策添,并在Execute()
方法中調(diào)用了SubsystemC
的方法。
客戶端使用代碼保持不變毫缆,仍只需創(chuàng)建外觀對(duì)象并調(diào)用Execute()
方法唯竹,即可同時(shí)調(diào)用子系統(tǒng)A、B和C的相應(yīng)方法苦丁,完成操作:
// 客戶端操作保持不變
func main() {
facade := NewFacade()
facade.Execute()
}
與中介者模式的不同
外觀模式和中介者模式的確有一些相似之處浸颓,但它們的主要目的和實(shí)現(xiàn)方式有所不同。
外觀模式的主要目的是簡(jiǎn)化客戶端與復(fù)雜子系統(tǒng)之間的交互芬骄,提供一個(gè)統(tǒng)一的接口或門(mén)面猾愿,隱藏子系統(tǒng)的復(fù)雜性。外觀模式通過(guò)封裝子系統(tǒng)账阻,使得客戶端可以更方便地使用子系統(tǒng)的功能蒂秘,但客戶端仍然直接與外觀對(duì)象進(jìn)行交互。
中介者模式的主要目的是減少對(duì)象之間的直接耦合淘太,將對(duì)象間的交互通過(guò)一個(gè)中介對(duì)象進(jìn)行協(xié)調(diào)姻僧。中介者模式通過(guò)將對(duì)象間的通信集中到一個(gè)中介對(duì)象中,從而降低了對(duì)象間的依賴關(guān)系蒲牧。對(duì)象不再直接相互引用撇贺,而是通過(guò)中介者對(duì)象來(lái)進(jìn)行通信。
以下是一個(gè)使用Go語(yǔ)言實(shí)現(xiàn)外觀模式和中介者模式進(jìn)行對(duì)比的示例代碼:
// 外觀模式示例
// SubsystemA 是子系統(tǒng)A
type SubsystemA struct{}
func (s *SubsystemA) MethodA() {
fmt.Println("SubsystemA: MethodA")
}
// SubsystemB 是子系統(tǒng)B
type SubsystemB struct{}
func (s *SubsystemB) MethodB() {
fmt.Println("SubsystemB: MethodB")
}
// Facade 是外觀
type Facade struct {
subsystemA *SubsystemA
subsystemB *SubsystemB
}
func NewFacade() *Facade {
return &Facade{
subsystemA: &SubsystemA{},
subsystemB: &SubsystemB{},
}
}
func (f *Facade) Execute() {
f.subsystemA.MethodA()
f.subsystemB.MethodB()
}
// 中介者模式示例
// Mediator 是中介者
type Mediator struct {
colleagueA *ColleagueA
colleagueB *ColleagueB
}
func NewMediator() *Mediator {
return &Mediator{}
}
func (m *Mediator) SetColleagueA(colleagueA *ColleagueA) {
m.colleagueA = colleagueA
}
func (m *Mediator) SetColleagueB(colleagueB *ColleagueB) {
m.colleagueB = colleagueB
}
func (m *Mediator) CoordinateA() {
// 協(xié)調(diào)邏輯
fmt.Println("Mediator: Coordinate A")
m.colleagueB.ActionB()
}
func (m *Mediator) CoordinateB() {
// 協(xié)調(diào)邏輯
fmt.Println("Mediator: Coordinate B")
m.colleagueA.ActionA()
}
// ColleagueA 是同事A
type ColleagueA struct {
mediator *Mediator
}
func NewColleagueA(mediator *Mediator) *ColleagueA {
return &ColleagueA{mediator: mediator}
}
func (c *ColleagueA) ActionA() {
fmt.Println("ColleagueA: Action A")
c.mediator.CoordinateA()
}
// ColleagueB 是同事B
type ColleagueB struct {
mediator *Mediator
}
func NewColleagueB(mediator *Mediator) *ColleagueB {
return &ColleagueB{mediator: mediator}
}
func (c *ColleagueB) ActionB() {
fmt.Println("ColleagueB: Action B")
c.mediator.CoordinateB()
}
func main() {
// 外觀模式示例
facade := NewFacade()
facade.Execute()
// 中介者模式示例
mediator := NewMediator()
colleagueA := NewColleagueA(mediator)
colleagueB := NewColleagueB(mediator)
mediator.SetColleagueA(colleagueA)
mediator.SetColleagueB(colleagueB)
colleagueA.ActionA()
}
在示例中冰抢,外觀模式通過(guò)封裝子系統(tǒng)A和B提供了統(tǒng)一的接口外觀對(duì)象(Facade)松嘶,客戶端只需與外觀對(duì)象進(jìn)行交互。
而中介者模式中挎扰,中介者對(duì)象(Mediator)被用來(lái)協(xié)調(diào)同事對(duì)象(ColleagueA和ColleagueB)之間的交互翠订,同事對(duì)象不直接耦合,而是通過(guò)中介者進(jìn)行通信遵倦。
總結(jié)起來(lái)尽超,外觀模式主要簡(jiǎn)化了客戶端與復(fù)雜子系統(tǒng)之間的接口,而中介者模式是用來(lái)減少對(duì)象間直接耦合梧躺。
總結(jié)
設(shè)計(jì)模式中的外觀模式旨在簡(jiǎn)化客戶端與復(fù)雜子系統(tǒng)之間的交互似谁,通過(guò)提供一個(gè)統(tǒng)一的接口或門(mén)面來(lái)隱藏子系統(tǒng)的復(fù)雜性。外觀模式封裝了子系統(tǒng)的一組接口掠哥,使客戶端更容易使用子系統(tǒng)的功能巩踏。
外觀對(duì)象本身在未來(lái)的擴(kuò)展中需要保持穩(wěn)定,如果需要擴(kuò)展或修改子系統(tǒng)的功能续搀,可以通過(guò)添加新的子系統(tǒng)塞琼、修改子系統(tǒng)的行為或通過(guò)繼承和重寫(xiě)外觀對(duì)象來(lái)實(shí)現(xiàn)。
與外觀模式相比目代,中介者模式的主要目的是減少對(duì)象之間的直接耦合屈梁。中介者模式通過(guò)引入一個(gè)中介者對(duì)象,將對(duì)象間的通信集中到該對(duì)象中進(jìn)行協(xié)調(diào)榛了,從而降低了對(duì)象間的依賴關(guān)系在讶。中介者模式中,對(duì)象不再直接相互引用霜大,而是通過(guò)中介者對(duì)象來(lái)進(jìn)行通信构哺。總的來(lái)說(shuō)战坤,外觀模式和中介者模式在目的和實(shí)現(xiàn)方式上存在區(qū)別:外觀模式簡(jiǎn)化了客戶端與復(fù)雜子系統(tǒng)之間的交互曙强,中介者模式減少對(duì)象間的直接耦合。外觀模式通過(guò)封裝子系統(tǒng)提供統(tǒng)一的接口途茫,而中介者模式通過(guò)引入中介者對(duì)象協(xié)調(diào)對(duì)象間的交互碟嘴。