侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Laravel内核分析-设计模式之外观模式

Laravel  /  管理员 发布于 2年前   372

外观模式描述:

外观模式 (Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

Laravel 中我们常用到的 Route、Redis、Auth 这些 Facade 就是外观模式的具体实现, 在 Laravel 中设计了多个外观类,每个外观类继承自统一的抽象外观类,在抽象外观类里提供了通过外观类访问其背后子系统的基础方法。

对于新的业务需求,不要修改原有外观类,而应该增加一个新的具体外观类,由新的具体外观类来关联新的子系统对象,同时通过修改配置文件来达到不修改源代码并更换外观类的目的。 

下面是一个简单的外观模式的例子,并没有引入抽象外观类,在介绍 Laravel Facade 的文章中我们会看到 Laravel 里提供了一个抽象外观类从而让我们能够方便的根据需要增加新子系统的外观类,并让外观类能够正确代理到其对应的子系统 (或者叫服务)。


模式结构:

外观模式包含如下角色:

1.Facade 外观角色

2.SubSystem 子系统角色

1.png

代码示例

<?php
class Client
{
    public function main()
    {
        (new Facade)->operation();
    }
}
class Facade
{
    private $systemA;
    private $systemB;
    public function __construct()
    {
        $this->systemA = new SystemA;
        $this->systemB = new SystemB;
    }
    public function operation()
    {
        $this->systemA->operationA();
        $this->systemB->operationB();
    }
}
class SystemA
{
    public function operationA()
    {
        //
    }
}
class SystemB
{
    public function operationB()
    {
        //
    }
}

模式分析:

根据 “单一职责原则”,在软件中将一个系统划分为若干个子系统有利于降低整个系统的复杂性,一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小,而达到该目标的途径之一就是引入一个外观对象,它为子系统的访问提供了一个简单而单一的入口。 - 外观模式也是 “迪米特法则” 的体现,通过引入一个新的外观类可以降低原有系统的复杂度,同时降低客户类与子系统类的耦合度。 - 外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交道。 - 外观模式的目的在于降低系统的复杂程度。 - 外观模式从很大程度上提高了客户端使用的便捷性,使得客户端无须关心子系统的工作细节,通过外观角色即可调用相关功能。


外观模式的缺点:

不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。

在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了 “开闭原则”。


模式扩展:

1.一个系统有多个外观类

在外观模式中,通常只需要一个外观类,并且此外观类只有一个实例,换言之它是一个单例类。在很多情况下为了节约系统资源,一般将外观类设计为单例类。当然这并不意味着在整个系统里只能有一个外观类,在一个系统中可以设计多个外观类,每个外观类都负责和一些特定的子系统交互,向用户提供相应的业务功能。


2.不要试图通过外观类为子系统增加新行为

不要通过继承一个外观类在子系统中加入新的行为,这种做法是错误的。外观模式的用意是为子系统提供一个集中化和简化的沟通渠道,而不是向子系统加入新的行为,新的行为的增加应该通过修改原有子系统类或增加新的子系统类来实现,不能通过外观类来实现。


3.抽象外观类的引入

外观模式最大的缺点在于违背了 “开闭原则”,当增加新的子系统或者移除子系统时需要修改外观类,可以通过引入抽象外观类在一定程度上解决该问题,客户端针对抽象外观类进行编程。对于新的业务需求,不修改原有外观类,而对应增加一个新的具体外观类,由新的具体外观类来关联新的子系统对象,同时通过修改配置文件来达到不修改源代码并更换外观类的目的。



总结:

1.在外观模式中,外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。


2.外观模式包含两个角色:外观角色是在客户端直接调用的角色,在外观角色中可以知道相关的 (一个或者多个) 子系统的功能和责任,它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理;在软件系统中可以同时有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能。


3.外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交道。


4.外观模式主要优点在于对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易,它实现了子系统与客户之间的松耦合关系,并降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程;其缺点在于不能很好地限制客户使用子系统类,而且在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了 “开闭原则”。


5.外观模式适用情况包括:要为一个复杂子系统提供一个简单接口;客户程序与多个子系统之间存在很大的依赖性;在层次化结构中,需要定义系统中每一层的入口,使得层与层之间不直接产生联系。


转:https://learnku.com/docs/laravel-kernel/design-mode-appearance-mode/6917


  • 上一条:
    分享Laravel中的10个很方便且比较冷门的用法
    下一条:
    Laravel内核分析-设计模式之装饰模式
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在Laravel项目中使用中间件方式统计用户在线时长功能代码示例(0个评论)
    • 在Laravel中构建业务流程模型(0个评论)
    • 在Laravel项目中的实现无密码认证之:发送邮箱链接授权(0个评论)
    • Laravel 10.4版本发布(0个评论)
    • 在laravel框架中的5个HTTP客户端技巧分享(0个评论)
    • 近期文章
    • 如何优雅处理async await错误推荐:await-to-js库(0个评论)
    • lodash工具库(0个评论)
    • 在Laravel项目中使用中间件方式统计用户在线时长功能代码示例(0个评论)
    • 在Laravel中构建业务流程模型(0个评论)
    • windows系统中安装FFMpeg及在phpstudy环境php7.3 + php-ffmpeg扩展的使用流程步骤(0个评论)
    • 在go语言中对浮点的数组、切片(slice)进行正向排序和反向排序(0个评论)
    • 在go语言中对整数数组、切片(slice)进行排序和反向排序(0个评论)
    • 在go语言中对字符串数组、切片(slice)进行排序和反向排序(0个评论)
    • 最新国内免注册ChatGPT体验站_ChatGPT镜像站访问链接地址2023/3/28持续更新(0个评论)
    • 在Laravel项目中的实现无密码认证之:发送邮箱链接授权(0个评论)
    • 近期评论
    • 博主 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 @ xiaoB 你只管努力,剩下的叫给天意;天若有情天亦老,..
    • xiaoB 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 会不会春节放假后又阳一次?..
    • BUG4 在

      你翻墙过吗?国内使用vpn翻墙可能会被网警抓,你需了解的事中评论 不是吧?..
    • 博主 在

      go语言+beego框架中获取get,post请求的所有参数中评论 @ t1  直接在router.go文件中配就ok..
    • Jade 在

      如何在MySQL查询中获得当月记录中评论 Dear zongscan.com team, We can skyroc..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-01
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客