ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、视频、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 外观模式(门面(Facade)模式) 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。 > 将多个类对象统一到facade类的某个方法中输出 外观(Facade)模式是“迪米特法则”的典型应用, **主要优点。** 1. 降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类。 2. 对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易。 3. 降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程,因为编译一个子系统不会影响其他的子系统,也不会影响外观对象。 **主要缺点。** 1. 不能很好地限制客户使用子系统类。 2. 增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。 **模式的结构** 外观(Facade)模式包含以下主要角色。 1. 外观(Facade)角色:为多个子系统对外提供一个共同的接口。 2. 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。 3. 客户(Client)角色:通过一个外观角色访问各个子系统的功能。 ![](https://img.kancloud.cn/4d/35/4d35a07a7ca50fe0643a6e54e6019007_509x539.png) ``` <pre class="calibre10">``` <span class="token">//外观角色</span> class <span class="token4">Facade</span> <span class="token3">{</span> private $obj1<span class="token3">;</span> private $obj2<span class="token3">;</span> private $obj3<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>obj1<span class="token1">=</span><span class="token5">new</span> <span class="token4">SubSystem01</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj2<span class="token1">=</span><span class="token5">new</span> <span class="token4">SubSystem02</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj3<span class="token1">=</span><span class="token5">new</span> <span class="token4">SubSystem03</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">method</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>obj1<span class="token1">-</span><span class="token1">></span><span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj2<span class="token1">-</span><span class="token1">></span><span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj3<span class="token1">-</span><span class="token1">></span><span class="token4">method3</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//子系统角色1</span> class <span class="token4">SubSystem01</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"子系统01的method1()被调用!<br>"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//子系统角色2</span> class <span class="token4">SubSystem02</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"子系统02的method2()被调用!<br>"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//子系统角色3</span> class <span class="token4">SubSystem03</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">method3</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"子系统03的method3()被调用!<br>"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> class <span class="token4">Client</span> <span class="token3">{</span> public static <span class="token5">function</span> <span class="token4">main</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $f<span class="token1">=</span><span class="token5">new</span> <span class="token4">Facade</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $f<span class="token1">-</span><span class="token1">></span><span class="token4">method</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> Client<span class="token3">:</span><span class="token3">:</span><span class="token4">main</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> 结果: 子系统<span class="token6">01</span>的<span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span>被调用! 子系统<span class="token6">02</span>的<span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span>被调用! 子系统<span class="token6">03</span>的<span class="token4">method3</span><span class="token3">(</span><span class="token3">)</span>被调用! ``` ``` ## **外观模式的应用场景** 通常在以下情况下可以考虑使用外观模式。 1. 对分层结构系统构建时,使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系。 2. 当一个复杂系统的子系统很多时,外观模式可以为系统设计一个简单的接口供外界访问。 3. 当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离,从而提高子系统的独立性和可移植性。 ## **外观模式的扩展** 在外观模式中,当增加或移除子系统时需要修改外观类或客户端的源代码,这违背了“开闭原则”。如果引入抽象外观类,则在一定程度上解决了该问题, 在引入抽象外观类之后,客户端可以针对抽象外观类进行编程,对于新的业务需求,不需要修改原有外观类,而对应增加一个新的具体外观类,由新的具体外观类来关联新的子系统对象,同时通过修改配置文件来达到不修改任何源代码并更换外观类的目的。 其结构图如图所示。 ![](https://img.kancloud.cn/a8/58/a8581ae250de2bc82dddba75f3f30c5a_540x532.png) ``` <pre class="calibre10">``` <span class="token">//子系统角色1</span> class <span class="token4">SubSystem01</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"子系统01的method1()被调用!<br>"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//子系统角色2</span> class <span class="token4">SubSystem02</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"子系统02的method2()被调用!<br>"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//子系统角色3</span> class <span class="token4">SubSystem03</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">method3</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"子系统03的method3()被调用!<br>"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//子系统角色4</span> class <span class="token4">SubSystem04</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">method4</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"子系统04的method4()被调用!<br>"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> abstract class <span class="token4">AbstractFacade</span><span class="token3">{</span> abstract public <span class="token5">function</span> <span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> abstract public <span class="token5">function</span> <span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//原外观角色类</span> class <span class="token4">Facade1</span> extends <span class="token4">AbstractFacade</span> <span class="token3">{</span> private $obj1<span class="token3">;</span> private $obj2<span class="token3">;</span> private $obj3<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>obj1<span class="token1">=</span><span class="token5">new</span> <span class="token4">SubSystem01</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj2<span class="token1">=</span><span class="token5">new</span> <span class="token4">SubSystem02</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj3<span class="token1">=</span><span class="token5">new</span> <span class="token4">SubSystem03</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>obj1<span class="token1">-</span><span class="token1">></span><span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj2<span class="token1">-</span><span class="token1">></span><span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj3<span class="token1">-</span><span class="token1">></span><span class="token4">method3</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span><span class="token3">}</span> <span class="token3">}</span> <span class="token">//添加或者删除子系统角色而新增加外观角色类</span> class <span class="token4">Facade2</span> extends <span class="token4">AbstractFacade</span> <span class="token3">{</span> private $obj2<span class="token3">;</span> private $obj3<span class="token3">;</span> private $obj4<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>obj2<span class="token1">=</span><span class="token5">new</span> <span class="token4">SubSystem02</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj3<span class="token1">=</span><span class="token5">new</span> <span class="token4">SubSystem03</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj4<span class="token1">=</span><span class="token5">new</span> <span class="token4">SubSystem04</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>obj2<span class="token1">-</span><span class="token1">></span><span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj3<span class="token1">-</span><span class="token1">></span><span class="token4">method3</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>obj4<span class="token1">-</span><span class="token1">></span><span class="token4">method4</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span><span class="token3">}</span> <span class="token3">}</span> class <span class="token4">Client</span> <span class="token3">{</span> public static <span class="token5">function</span> <span class="token4">main</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $f<span class="token1">=</span><span class="token5">new</span> <span class="token4">Facade1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $f<span class="token1">-</span><span class="token1">></span><span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//当移除子系统角色1,添加子系统角色4时,我们只需要重新定义Facade2即可</span> $f<span class="token1">=</span><span class="token5">new</span> <span class="token4">Facade2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $f<span class="token1">-</span><span class="token1">></span><span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> Client<span class="token3">:</span><span class="token3">:</span><span class="token4">main</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> ``` ``` 结果: ``` <pre class="calibre10">``` 子系统<span class="token6">01</span>的<span class="token4">method1</span><span class="token3">(</span><span class="token3">)</span>被调用! 子系统<span class="token6">02</span>的<span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span>被调用! 子系统<span class="token6">03</span>的<span class="token4">method3</span><span class="token3">(</span><span class="token3">)</span>被调用! 子系统<span class="token6">02</span>的<span class="token4">method2</span><span class="token3">(</span><span class="token3">)</span>被调用! 子系统<span class="token6">03</span>的<span class="token4">method3</span><span class="token3">(</span><span class="token3">)</span>被调用! 子系统<span class="token6">04</span>的<span class="token4">method4</span><span class="token3">(</span><span class="token3">)</span>被调用! ``` ``` **文件加密的门面模式例子** ``` <pre class="calibre10">``` <span class="token">//读取并返回配置文件的内容</span> <span class="token5">function</span> <span class="token4">config</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">{</span> <span class="token">//这里就不读取配置文件,简单返回测试下</span> <span class="token5">return</span> <span class="token2">"CipherMachine"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//抽象门面类</span> abstract class <span class="token4">AbstractEncryptFacade</span> <span class="token3">{</span> abstract public <span class="token5">function</span> <span class="token4">FileEncrypt</span><span class="token3">(</span>string $fileNameSrc<span class="token3">,</span> string $fileNameDes<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">// 旧加密类</span> class <span class="token4">CipherMachine</span><span class="token3">{</span> public <span class="token5">function</span> <span class="token4">Encrypt</span><span class="token3">(</span>$plainText<span class="token3">)</span><span class="token3">{</span> <span class="token">//省略加密规则</span> $encryptText<span class="token1">=</span><span class="token2">"旧加密类加密后的字符串"</span><span class="token3">;</span> <span class="token5">return</span> $encryptText<span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">// 原门面类</span> <span class="token">// 新的门面类</span> class <span class="token4">EncryptFacade</span> extends <span class="token4">AbstractEncryptFacade</span> <span class="token3">{</span> <span class="token">//文件源内容</span> private $plainStr<span class="token3">;</span> <span class="token">//加密对象</span> private $cipher<span class="token3">;</span> <span class="token">//文件加密后的内容</span> private $encryptStr<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">EncryptFacade</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>cipher <span class="token1">=</span> <span class="token5">new</span> <span class="token4">CipherMachine</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//其他对象</span> <span class="token">//... ...</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">FileEncrypt</span><span class="token3">(</span>string $fileNameSrc<span class="token3">,</span> string $fileNameDes<span class="token3">)</span> <span class="token3">{</span> <span class="token">//读取文件内容</span> $this<span class="token1">-</span><span class="token1">></span>plainStr <span class="token1">=</span> <span class="token4">file_get_contents</span><span class="token3">(</span>$fileNameSrc<span class="token3">)</span><span class="token3">;</span> <span class="token">//返回加密后的文件内容</span> $this<span class="token1">-</span><span class="token1">></span>encryptStr <span class="token1">=</span> $this<span class="token1">-</span><span class="token1">></span>cipher<span class="token1">-</span><span class="token1">></span><span class="token4">Encrypt</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>plainStr<span class="token3">)</span><span class="token3">;</span> <span class="token">//将加密文件内容写入文件中</span> <span class="token4">file_put_contents</span><span class="token3">(</span>$fileNameDes<span class="token3">,</span>$this<span class="token1">-</span><span class="token1">></span>encryptStr<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">// 新加密类</span> class <span class="token4">NewCipherMachine</span><span class="token3">{</span> public <span class="token5">function</span> <span class="token4">Encrypt</span><span class="token3">(</span>$plainText<span class="token3">)</span><span class="token3">{</span> <span class="token">//省略加密规则 </span> $encryptText<span class="token1">=</span><span class="token2">"新加密类加密后的字符串"</span><span class="token3">;</span> <span class="token5">return</span> $encryptText<span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">// 新的门面类</span> class <span class="token4">NewEncryptFacade</span> extends <span class="token4">AbstractEncryptFacade</span> <span class="token3">{</span> <span class="token">//文件源内容</span> private $plainStr<span class="token3">;</span> <span class="token">//加密对象</span> private $cipher<span class="token3">;</span> <span class="token">//文件加密后的内容</span> private $encryptStr<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">NewEncryptFacade</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>cipher <span class="token1">=</span> <span class="token5">new</span> <span class="token4">NewCipherMachine</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">FileEncrypt</span><span class="token3">(</span>string $fileNameSrc<span class="token3">,</span> string $fileNameDes<span class="token3">)</span> <span class="token3">{</span> <span class="token">//读取文件内容</span> $this<span class="token1">-</span><span class="token1">></span>plainStr <span class="token1">=</span> <span class="token4">file_get_contents</span><span class="token3">(</span>$fileNameSrc<span class="token3">)</span><span class="token3">;</span> <span class="token">//返回加密后的文件内容</span> $this<span class="token1">-</span><span class="token1">></span>encryptStr <span class="token1">=</span> $this<span class="token1">-</span><span class="token1">></span>cipher<span class="token1">-</span><span class="token1">></span><span class="token4">Encrypt</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>plainStr<span class="token3">)</span><span class="token3">;</span> <span class="token">//将加密文件内容写入文件中</span> <span class="token4">file_put_contents</span><span class="token3">(</span>$fileNameDes<span class="token3">,</span>$this<span class="token1">-</span><span class="token1">></span>encryptStr<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> class <span class="token4">Client</span><span class="token3">{</span> public static <span class="token5">function</span> <span class="token4">main</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> <span class="token">//读取配置文件</span> $conf<span class="token1">=</span><span class="token4">config</span><span class="token3">(</span><span class="token2">"encrypt.type"</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//根据配置文件的值加密文件</span> <span class="token5">if</span> <span class="token3">(</span>$conf<span class="token1">==</span><span class="token2">"CipherMachine"</span><span class="token3">)</span> <span class="token3">{</span> <span class="token3">(</span><span class="token5">new</span> <span class="token4">EncryptFacade</span><span class="token3">)</span><span class="token1">-</span><span class="token1">></span><span class="token4">FileEncrypt</span><span class="token3">(</span><span class="token2">"./test.txt"</span><span class="token3">,</span><span class="token2">"newtest.txt"</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span><span class="token5">else</span><span class="token3">{</span> <span class="token3">(</span><span class="token5">new</span> <span class="token4">NewEncryptFacade</span><span class="token3">)</span><span class="token1">-</span><span class="token1">></span><span class="token4">FileEncrypt</span><span class="token3">(</span><span class="token2">"./test.txt"</span><span class="token3">,</span><span class="token2">"newtest.txt"</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> Client<span class="token3">:</span><span class="token3">:</span><span class="token4">main</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> ``` ``` **例子:tp的门面模式** ``` <pre class="calibre17">``` namespace app\admin<span class="token3">;</span> class <span class="token4">Test</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">hello</span><span class="token3">(</span>$name<span class="token3">)</span> <span class="token3">{</span> <span class="token5">return</span> <span class="token2">'你好啊,'</span> <span class="token3">.</span> $name<span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> namespace think<span class="token3">;</span> <span class="token">/** * Facade管理类 */</span> class <span class="token4">Facade</span> <span class="token3">{</span> <span class="token">/** * 始终创建新的对象实例 * @var bool */</span> protected static $alwaysNewInstance<span class="token3">;</span> <span class="token">/** * 创建Facade实例 * @static * @access protected * @param string $class 类名或标识 * @param array $args 变量 * @param bool $newInstance 是否每次创建新的实例 * @return object */</span> protected static <span class="token5">function</span> <span class="token4">createFacade</span><span class="token3">(</span>string $class <span class="token1">=</span> <span class="token2">''</span><span class="token3">,</span> array $args <span class="token1">=</span> <span class="token3">[</span><span class="token3">]</span><span class="token3">,</span> bool $newInstance <span class="token1">=</span> <span class="token6">false</span><span class="token3">)</span> <span class="token3">{</span> $class <span class="token1">=</span> $class <span class="token1">?</span><span class="token3">:</span> static<span class="token3">:</span><span class="token3">:</span>class<span class="token3">;</span><span class="token">//app\facade\Test</span> $facadeClass <span class="token1">=</span> static<span class="token3">:</span><span class="token3">:</span><span class="token4">getFacadeClass</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//app\facade\Test 即Test子类的getFacadeClass返回的结果</span> <span class="token5">if</span> <span class="token3">(</span>$facadeClass<span class="token3">)</span> <span class="token3">{</span> $class <span class="token1">=</span> $facadeClass<span class="token3">;</span> <span class="token3">}</span> <span class="token5">if</span> <span class="token3">(</span>static<span class="token3">:</span><span class="token3">:</span>$alwaysNewInstance<span class="token3">)</span> <span class="token3">{</span> $newInstance <span class="token1">=</span> <span class="token6">true</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//Container::getInstance() 实例化Container类 make()方法则实例化传入的类并将此类对象挂载到instance属性上(注册树模式?)</span> <span class="token">//返回 实例化成功的类对象这里是指app\facade\Test</span> <span class="token5">return</span> Container<span class="token3">:</span><span class="token3">:</span><span class="token4">getInstance</span><span class="token3">(</span><span class="token3">)</span><span class="token1">-</span><span class="token1">></span><span class="token4">make</span><span class="token3">(</span>$class<span class="token3">,</span> $args<span class="token3">,</span> $newInstance<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">/** * 获取当前Facade对应类名 * @access protected * @return string */</span> protected static <span class="token5">function</span> <span class="token4">getFacadeClass</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span><span class="token3">}</span> <span class="token">/** * 带参数实例化当前Facade类 * @access public * @return object */</span> public static <span class="token5">function</span> <span class="token4">instance</span><span class="token3">(</span><span class="token3">.</span><span class="token3">.</span><span class="token3">.</span>$args<span class="token3">)</span> <span class="token3">{</span> <span class="token5">if</span> <span class="token3">(</span>__CLASS__ <span class="token1">!=</span> static<span class="token3">:</span><span class="token3">:</span>class<span class="token3">)</span> <span class="token3">{</span> <span class="token5">return</span> self<span class="token3">:</span><span class="token3">:</span><span class="token4">createFacade</span><span class="token3">(</span><span class="token2">''</span><span class="token3">,</span> $args<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">/** * 调用类的实例 * @access public * @param string $class 类名或者标识 * @param array|true $args 变量 * @param bool $newInstance 是否每次创建新的实例 * @return object */</span> public static <span class="token5">function</span> <span class="token4">make</span><span class="token3">(</span>string $class<span class="token3">,</span> $args <span class="token1">=</span> <span class="token3">[</span><span class="token3">]</span><span class="token3">,</span> $newInstance <span class="token1">=</span> <span class="token6">false</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">if</span> <span class="token3">(</span>__CLASS__ <span class="token1">!=</span> static<span class="token3">:</span><span class="token3">:</span>class<span class="token3">)</span> <span class="token3">{</span> <span class="token5">return</span> self<span class="token3">:</span><span class="token3">:</span><span class="token4">__callStatic</span><span class="token3">(</span><span class="token2">'make'</span><span class="token3">,</span> <span class="token4">func_get_args</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">if</span> <span class="token3">(</span><span class="token6">true</span> <span class="token1">===</span> $args<span class="token3">)</span> <span class="token3">{</span> <span class="token">// 总是创建新的实例化对象</span> $newInstance <span class="token1">=</span> <span class="token6">true</span><span class="token3">;</span> $args <span class="token1">=</span> <span class="token3">[</span><span class="token3">]</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">return</span> self<span class="token3">:</span><span class="token3">:</span><span class="token4">createFacade</span><span class="token3">(</span>$class<span class="token3">,</span> $args<span class="token3">,</span> $newInstance<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">// 调用实际类的方法 调用一个不存在或者不能访问的静态方法时触发此方法</span> public static <span class="token5">function</span> <span class="token4">__callStatic</span><span class="token3">(</span>string $method<span class="token3">,</span> array $params<span class="token3">)</span> <span class="token3">{</span> <span class="token">//$method为调用的不存在的那个方法, $params则是不存在这个方法的参数</span> <span class="token5">return</span> <span class="token4">call_user_func_array</span><span class="token3">(</span><span class="token3">[</span>static<span class="token3">:</span><span class="token3">:</span><span class="token4">createFacade</span><span class="token3">(</span><span class="token3">)</span><span class="token3">,</span> $method<span class="token3">]</span><span class="token3">,</span> $params<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> namespace app\facade<span class="token3">;</span> use think\Facade<span class="token3">;</span> class <span class="token4">Test</span> extends <span class="token4">Facade</span> <span class="token3">{</span> protected static <span class="token5">function</span> <span class="token4">getFacadeClass</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">return</span> <span class="token2">'app\admin\Test'</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//通常</span> $test <span class="token1">=</span> <span class="token5">new</span> <span class="token4"><span class="token3">\</span>app<span class="token3">\</span>admin<span class="token3">\</span>Test</span><span class="token3">;</span> echo $test<span class="token1">-</span><span class="token1">></span><span class="token4">hello</span><span class="token3">(</span><span class="token2">'thinkphp框架'</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 输出 你好啊,thinkphp框架</span> <span class="token">// 使用facade就 无需进行实例化 直接以静态方法方式调用hello方法</span> echo \app\facade\Test<span class="token3">:</span><span class="token3">:</span><span class="token4">hello</span><span class="token3">(</span><span class="token2">'thinkphp框架'</span><span class="token3">)</span><span class="token3">;</span> ``` ```