结构型-外观模式

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

简介

外观模式隐藏了系统的复杂性,为子系统中的一组接口提供了一个统一的高层接口,客户端通过高层接口访问子系统,不需要了解子系统的内部细节,这样使子系统更容易使用。

实际开发中因为需求变动,可能导致系统趋于复杂,在使用某些类时可能需要了解类的详细细节,比如方法调动步骤以及调用顺序,使用不当则会导致错误。

外观模式用于解决类似问题,由外观模式提供高层级的简单接口,调用者只要请求外观接口就能得到准确结果,不需要调用者去处理类的内部复杂逻辑。

外观模式还适用于处理子系统之间调用问题,保持子系统的独立性,一般而言,子系统之间相互依赖、相互调用,外观模式可以整合子系统的接口形成统一接口,定义更高级的接口让子系统更容易使用,提高独立性、层次性。

image

模式角色

门面角色:被客户角色调用,提供对子系统接口的高层次访问;

子系统角色:提供实际功能,被外观角色调用,但是不会调用外观角色;

客户端角色:不关心系统内部复杂子系统的运作情况,而只与外观角色通信获取数据。

image

适用场景

软件系统复杂度较高,需要提供一个更高级别的简单接口简化对子系统的操作;

客户端与实现类间有太多依赖,需要降低耦合性;

多个子系统互相依赖,此时需要层级化子系统,简化子系统之间的依赖性。

示例

假设有三个子系统,当客户端执行某一业务时,需要涉及到这三个子系统,且包含调用顺序:

public class SubSystemA {
 
    public void methodA(){
        System.out.println("1. 子系统A执行方法A");
    }
}
public class SubSystemB {
 
    public void methodB(){
        System.out.println("2. 子系统B执行方法B");
    }
}
public class SubSystemC {
    
    public void methodC(){
        System.out.println("3. 子系统C执行方法C");
    }
}

门面类:

public class Facade {
 
    private SubSystemA a;
    private SubSystemB b;
    private SubSystemC c;
    
    public Facade() {
        a = new SubSystemA();
        b = new SubSystemB();
        c = new SubSystemC();
    }
    
    public void execute(){
        a.methodA();
        b.methodB();
        c.methodC();
    }
}

客户端角色:

public class Cilent {

    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.execute();
    }
}

客户端执行业务时,不需要了解需要涉及几个子系统,也不需要了解子系统的调用顺序,这些对于客户端都是透明的。客户端只需要和门面通信就能获得自己想要的结果。

优点

松耦合

门面模式是符合迪米特法则(最少知识原则)的,迪米特法则强调了类和类之间应当保持松耦合关系,一个类应当尽可能少的与其他类发生相互作用,如果两个类不直接通信,那么这两个类就不应当发生直接的相互作用。如果一个类需要调用另一个类的某个方法,可以通过第三个类转发这个调用。

封装变化的部分

外观模式中,只要外观不发生变化,客户端就不会受任何影响,因为外观封装了对子系统中的变化,对于客户端是完全透明的。

image

jdk中的外观模式

java.util.logger.Logger类使用了外观模式,Logger类中包含了多个辅助类,客户端只需要通过调用Logger类,不需要了解其他多个辅助类的具体细节,从而实现了客户端和辅助类的解耦,简化了调用。

image

Logger:日志记录对象。用于记录日志信息。

Handler:用于处理日志信息的输出。在 Handler 类中,可以决定日志是输出到文件中还是控制台中(相当于log4j中的appender)。

Filter:用于过滤日志。在 Filter 类中,可以根据日志级别或者某种条件来决定是否输出该日志。这样达到去除冗余信息的目的。

Formatter:用于格式化日志信息。该类可以将日志文本格式化成 XML 或者 HTML 的格式,这完全依赖于具体的实现。

Level:用于表示日志的级别。 JDK 日志框架默认有如下级别:SEVERE(最高值) 、WARNING 、INFO 、CONFIG 、FINE 、FINER 、FINEST(最低值)、ALL(记录所有信息) OFF(不记录任何级别信息)。

和其他模式的关系

模板方法模式

模板方法模式中固定了方法的调用模板,而门面模式也有固定方法调用模板、次序的效果,但是模板方法模式一般固定的是本身的方法流程,且可以提供给子类重写。

组合模式

和组合模式一样,外观模式要实现对子系统的访问,一般情况下都需要将子系统角色组合到门面类中,从这个角度,和装饰模式、代理模式也有类似之处。

参考:《设计模式那点事》
https://www.alicharles.com/article/design-pattern/jdk-facade-pattern/

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
2月前
|
设计模式 缓存 算法
C#一分钟浅谈:组合模式与外观模式
【10月更文挑战第15天】本文介绍了面向对象设计模式中的组合模式和外观模式。组合模式通过树形结构表示“部分-整体”的层次关系,适用于文件系统、图形界面等场景;外观模式提供统一接口简化复杂系统的使用,适用于视频播放器等多模块系统。文章详细解释了这两种模式的基本概念、应用场景、实现方式及常见问题和解决方法,帮助读者更好地理解和应用。
42 9
|
7月前
结构型 装饰器模式
结构型 装饰器模式
33 0
|
设计模式 uml
结构型设计模式03-外观模式
结构型设计模式03-外观模式
44 0
|
6月前
|
设计模式 算法 关系型数据库
设计模式第七讲-外观模式、适配器模式、模板方法模式详解
系统要求所有的数据库帮助类必须实现ISqlHelp接口,面向该接口编程,如SQLServerHelp类。 此时第三方提供了一个新的MySql的帮助类(假设是dll,不能修改),它的编程规范和ISqlHelp不兼容,这个时候就需要引入适配器类,使二者能相互兼容。
176 0
|
7月前
|
前端开发
结构型 外观模式
结构型 外观模式
30 0
|
7月前
|
存储 安全
结构型 组合模式
结构型 组合模式
32 0
|
7月前
|
设计模式 C++
结构型 适配器模式
结构型 适配器模式
41 0
|
设计模式 Java 中间件
设计模式-结构型模式:外观模式
设计模式-结构型模式:外观模式
107 0
|
应用服务中间件 智能硬件 容器
结构型模式-外观模式
结构型模式-外观模式
86 0
|
设计模式 JSON 前端开发
设计模式 - 结构型模式_外观模式
设计模式是解决程序中不合理、不易于扩展、不易于维护的问题,也是⼲掉⼤部分 ifelse 的利器,在我们常⽤的框架中基本都会⽤到⼤量的设计模式来构建组件,这样也能⽅便框架的升级和功能的扩展。 但如果不能合理的设计以及乱⽤设计模式,会导致整个编程变得更加复杂难维护,也就是我们常说的: 反设计 、 过渡设计 。⽽这部分设计能⼒也是从实践的项⽬中获取的经验,不断的改造优化摸索出的最合理的⽅式,应对当前的服务体量。
124 0
设计模式 - 结构型模式_外观模式