外观模式(Facade Pattern)是一种结构型设计模式,它为客户端提供一个简单、统一的接口,用以访问子系统中的一组接口。
在外观模式中,一个高层接口(即Facade)可以将多个复杂的子系统接口封装成一个简单的接口,从而提供给客户端一个更加简单的接口。
举个例子,我们可以考虑一个汽车制造工厂,该工厂包含引擎制造、悬挂制造、底盘制造、内饰制造等子系统。如果我们要制造一辆汽车,就需要逐个调用每个子系统来完成。但是,使用外观模式就可以将所有的操作封装成一个Facade类的方法,可以快速完成汽车的制造。
外观模式的优点包括:
- 简化客户端的调用过程,客户端只需要和Facade接口进行交互,不需要与子系统进行交互,从而使得客户端更加容易使用。
- 降低客户端与子系统之间的耦合度,使得子系统更加容易维护和修改。当需要修改子系统时,只需要修改Facade类即可,客户端无需做任何修改。
- 提高了系统的可重用性和灵活性,由于实现了子系统的封装,因此可以更加灵活地组合子系统的功能,生成新的功能组件,提高了系统的可重用性和灵活性。
当然,外观模式也存在一些缺点,例如,如果有新的功能需要添加到系统中,可能需要修改Facade类,这样会导致Facade类的代码变得复杂。另外,Facade类可能会变成一个“大杂烩”,包含了过多的功能,因此需要谨慎设计Facade类。
golang实现
package main
import "fmt"
// 子系统 1
type Subsystem1 interface {
Operation1() string
}
type subsystem1 struct {}
func NewSubsystem1() Subsystem1 {
return &subsystem1{}
}
func (*subsystem1) Operation1() string {
return "Subsystem1: 操作 1\n"
}
// 子系统 2
type Subsystem2 interface {
Operation2(number int) string
}
type subsystem2 struct {}
func NewSubsystem2() Subsystem2 {
return &subsystem2{}
}
func (*subsystem2) Operation2(number int) string {
return fmt.Sprintf("Subsystem2: 操作 2, 参数: %d\n", number)
}
// 外观
type Facade interface {
Operation() string
}
type facade struct {
subsystem1 Subsystem1
subsystem2 Subsystem2
}
func NewFacade() Facade {
return &facade{
subsystem1: NewSubsystem1(),
subsystem2: NewSubsystem2(),
}
}
func (f *facade) Operation() string {
result := "Facade 初始化子系统:\n"
result += f.subsystem1.Operation1()
result += f.subsystem2.Operation2(3)
return result
}
func main() {
facade := NewFacade()
fmt.Println(facade.Operation())
}
php实现
<?php
/**
* 子系统中的类A
*/
class ClassA
{
public function operationA()
{
echo 'ClassA->operationA() called' . PHP_EOL;
}
}
/**
* 子系统中的类B
*/
class ClassB
{
public function operationB()
{
echo 'ClassB->operationB() called' . PHP_EOL;
}
}
/**
* 子系统中的类C
*/
class ClassC
{
public function operationC()
{
echo 'ClassC->operationC() called' . PHP_EOL;
}
}
/**
* 外观类
*/
class Facade
{
private $classA;
private $classB;
private $classC;
public function __construct()
{
$this->classA = new ClassA();
$this->classB = new ClassB();
$this->classC = new ClassC();
}
public function operation()
{
$this->classA->operationA();
$this->classB->operationB();
$this->classC->operationC();
}
}
// 客户端代码
$facade = new Facade();
$facade->operation();
我们定义了三个子系统类ClassA、ClassB和ClassC,以及一个外观类Facade。客户端代码只需要实例化Facade类,然后调用其operation()方法,就可以间接地调用子系统中的三个方法。
在这个例子中,Facde类是用于隐藏子系统复杂性的简单接口。客户端只需要使用这个接口,并不需要了解子系统的细节。这种方式可以使客户端代码更加简单和易于维护。