门面模式
门面模式(Facade Pattern)是一种结构型设计模式,用于为复杂子系统提供一个统一、简单的接口,隐藏系统的复杂性。通过门面模式,客户端无需直接与系统的内部组件交互,而是通过门面类与系统打交道,简化了客户端的使用,降低了系统的复杂性和耦合度。
门面模式的主要概念
- 定义:门面模式通过提供一个高级接口,简化了子系统的使用。这个接口称为“门面”,它封装了复杂的子系统中的一系列方法或功能。客户端与门面类交互,门面类再去调用复杂子系统的各个模块。
- 参与者:
• 门面类(Facade):它是客户端与复杂子系统之间的接口。它知道哪些子系统类负责处理请求,并将请求委托给相应的子系统对象。
• 子系统类(Subsystems):这些是实际处理工作并执行请求的类。它们不需要知道门面的存在,通常是门面类将请求转发给它们。 - 客户端:客户端通过门面类来访问系统。它不需要知道子系统的内部结构,只需要与门面类交互即可。
主要作用 - 简化接口:门面模式为客户端提供一个简化的接口,避免直接与复杂的子系统交互。
- 松散耦合:门面模式将客户端与子系统解耦,客户端只需要知道门面类的接口,而不需要了解系统的详细实现。
- 更好的维护性:当系统需要扩展或修改时,可以只修改门面类或子系统中的部分模块,而不影响客户端。
门面模式的优缺点
优点 - 简化客户端使用:通过门面,客户端可以更轻松地使用复杂的子系统,而无需了解其内部细节。
- 降低耦合:门面将客户端和复杂系统解耦,修改子系统的实现不会影响客户端。
- 提高灵活性:可以轻松地对系统进行扩展或调整,门面类可以为子系统增加额外功能。
缺点 - 增加类的数量:引入了新的门面类,可能会使类的数量增加。
- 可能的性能开销:如果门面类过于庞大,可能会降低系统性能,特别是当所有请求都要经过门面时。
使用场景 - 简化复杂系统的访问:当系统非常复杂,包含多个模块,且这些模块经常需要被客户端使用时,可以引入门面模式。
- 减少耦合:当不希望客户端直接与子系统交互,希望通过一个简化的接口进行访问时,可以使用门面模式。
- 提供统一的接口:当需要提供一个标准的接口,供不同的客户端访问时,可以使用门面模式。
类比理解
可以将门面模式类比为现实中的“客服中心”。假设一家大公司有多个部门,如技术支持、财务、销售等。如果客户想要与这些部门交互,而不需要了解公司内部结构,客户可以打电话到客服中心,客服会根据客户需求连接到相应的部门,这个“客服中心”就是门面。
代码示例(伪代码):音响系统门面
设想我们有一个复杂的家庭影院系统,包含多个子系统组件,比如音响、DVD播放器、灯光控制等。我们希望通过一个门面接口来控制这些组件,而不是每次直接操作每个子系统。
- 子系统类
package main
import "fmt"
// 子系统1:音响系统
type Amplifier struct{}
func (a *Amplifier) On() {
fmt.Println("Amplifier is turned ON")
}
func (a *Amplifier) SetVolume(volume int) {
fmt.Printf("Amplifier volume is set to %d\n", volume)
}
func (a *Amplifier) Off() {
fmt.Println("Amplifier is turned OFF")
}
// 子系统2:DVD播放器
type DVDPlayer struct{}
func (d *DVDPlayer) Play(movie string) {
fmt.Printf("DVD Player is playing movie: %s\n", movie)
}
func (d *DVDPlayer) Stop() {
fmt.Println("DVD Player has stopped playing")
}
func (d *DVDPlayer) Eject() {
fmt.Println("DVD Player has ejected the disk")
}
// 子系统3:灯光控制
type Lights struct{}
func (l *Lights) Dim(level int) {
fmt.Printf("Lights dimmed to %d%%\n", level)
}
func (l *Lights) On() {
fmt.Println("Lights are ON")
}
func (l *Lights) Off() {
fmt.Println("Lights are OFF")
}
2. 门面类
// 门面类:家庭影院控制
type HomeTheaterFacade struct {
amplifier *Amplifier
dvdPlayer *DVDPlayer
lights *Lights
}
// 创建门面类的构造函数
func NewHomeTheaterFacade(amp *Amplifier, dvd *DVDPlayer, lights *Lights) *HomeTheaterFacade {
return &HomeTheaterFacade{
amplifier: amp,
dvdPlayer: dvd,
lights: lights,
}
}
// 通过门面类简化使用流程
func (ht *HomeTheaterFacade) WatchMovie(movie string) {
fmt.Println("Get ready to watch a movie...")
ht.lights.Dim(10)
ht.amplifier.On()
ht.amplifier.SetVolume(5)
ht.dvdPlayer.Play(movie)
}
func (ht *HomeTheaterFacade) EndMovie() {
fmt.Println("Shutting movie theater down...")
ht.dvdPlayer.Stop()
ht.dvdPlayer.Eject()
ht.amplifier.Off()
ht.lights.On()
}
3. 客户端代码
func main() {
// 创建子系统对象
amplifier := &Amplifier{}
dvdPlayer := &DVDPlayer{}
lights := &Lights{}
// 创建门面对象
homeTheater := NewHomeTheaterFacade(amplifier, dvdPlayer, lights)
// 使用门面对象控制子系统,简化客户端操作
homeTheater.WatchMovie("Inception")
fmt.Println()
homeTheater.EndMovie()
}
4. 输出结果
Get ready to watch a movie...
Lights dimmed to 10%
Amplifier is turned ON
Amplifier volume is set to 5
DVD Player is playing movie: Inception
Shutting movie theater down...
DVD Player has stopped playing
DVD Player has ejected the disk
Amplifier is turned OFF
Lights are ON
解释
- 子系统类:Amplifier、DVDPlayer 和 Lights 是家庭影院系统的子系统类,每个类都有自己的方法,比如打开/关闭设备、播放电影、调节灯光等。
- 门面类:HomeTheaterFacade 类是门面,它封装了对多个子系统的操作,通过提供简单的方法(WatchMovie 和 EndMovie),隐藏了子系统的复杂性。
- 客户端:客户端只需要调用门面类的接口,无需直接与子系统交互,从而简化了操作流程。
总结
门面模式的核心思想是“将复杂的系统隐藏起来,通过简单的接口与外部世界交互”,从而简化系统的使用,减少系统的耦合度,并提高系统的灵活性和可维护性。
中秋快乐
标签:fmt,Amplifier,----,Lights,门面,设计模式,子系统,客户端 From: https://www.cnblogs.com/zhifwu/p/18417169