专栏首页呆呆熊的技术路设计模式第六讲-外观模式(门面模式)

设计模式第六讲-外观模式(门面模式)

简介

外观模式(Facade,门面模式), 为子系统中额外一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

在项目开发和实际运用中十分频繁,但是其极易理解

图例:

外观不只是简化了接口,也将客户从组件的子系统中解耦. 外观和适配器可以包装许多类,但是外观的意图是简化接口,而适配器的意图是将接口转换成不同接口。

场景设置

似曾相识,有个超级复杂的论坛系统(客户端调用的相当复杂)。

下面我们将直接看看旧代码怎么写的吧

UserController 主流程类

package facade;

public class UserController {

    public static void main(String[] args) {

        //获取昵称
        UserInfo userInfo = new UserInfo();
        String userName = userInfo.getNickName();

        //获取最近登录时间
        UserSystem userSystem = new UserSystem();
        String lastLoginTime = userSystem.lastLoginTime();


        //获取用户点赞数
        UserBehavior userBehavior= new UserBehavior();
        int likeNum = userBehavior.getLikeNum();

        //todo
        //其它很多小类组成了供前端渲染的数据

        System.out.println("用户名" + userName + ",最近登录时间" + lastLoginTime+",喜欢了"+likeNum+"篇帖子");
    }

}

相关小类

用户信息相关

package facade;

public class UserInfo {

    public String getNickName(){
        return "许仙啊";
    }
}

用户系统相关:

package facade;

import java.text.SimpleDateFormat;
import java.util.Date;

public class UserSystem {

    public String lastLoginTime() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(new Date());
    }
}

用户行为相关:

package facade;

public class UserBehavior {

    public int getLikeNum() {
        return 5;
    }
}

output:

用户名许仙啊,最近登录时间2019-01-15 23:08:45,喜欢了5篇帖子

由此结构我们可以看出,对于我们的控制器来说是比较复杂的,对象涉及的比较多,当业务比较越来越大的时候,很容易出现耦合,无法拆分,只能在控制器中另创方法.

外观模式改造

核心-外观对象

package facade;

public class Facade {

    //用户信息对象
    private UserInfo userInfo;

    //用户系统信息对象
    private UserSystem userSystem;

    //用户行为对象
    private UserBehavior userBehavior;

    public Facade() {
        userInfo = new UserInfo();
        userSystem = new UserSystem();
        userBehavior = new UserBehavior();
    }

    public String getUserInfo() {

        String userName = userInfo.getNickName();

        String lastLoginTime = userSystem.lastLoginTime();

        int likeNum = userBehavior.getLikeNum();

        //todo
        //其它很多小类组成了供前端渲染的数据
        //可以按类别拆分到不同方法,也可以按功能需求一起,需要个人思考

        return "用户名" + userName + ",最近登录时间" + lastLoginTime+",喜欢了"+likeNum+"篇帖子";

    }

}

调用:

package facade;

public class UserController {

    public static void main(String[] args) {

        //外观对象
        Facade facade = new Facade();
        System.out.println(facade.getUserInfo());

    }
}

output:

用户名许仙啊,最近登录时间2019-01-15 23:19:16,喜欢了5篇帖子

UML图(图片来自网络)

我们由前置控制器移动到了getUserInfo方法中集体封装了。可能感觉并没有什么好处,但是它完美的体现了依赖倒转原则和迪米特法则的思想。

归纳总结

看到这里相信你敢相信这也算设计模式.其实外观模式有很多种灵活的拆分方式,对于封装系统的复杂度、提供更好的小类小功能的管理还是有非常大的用处的。

上文提到了迪米特法则,指的是如果两个类不必直接通信,那么这两个类就不应当发生直接的相互作用.如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用(此文的第三者指的就是我们的外观类) --摘自《大话设计模式》

什么时候应该使用呢

其实这是个层与层关系的问题,我们的控制器层和我们的系统实现层,随着业务的复杂度上升,他们之间的关系也会越来越复杂.

增加外观Facade层,对上层提供一个简单的接口,可以减少他们的依赖.

当维护一个遗留大型系统的时候,很难再此基础上拓展它难以维护下去,可能使用外观模式是非常好的一个选择。

最后谈一下和适配器模式的区别吧

区别是适配器只是适配一个类,外观模式作用多个类?

答案不对,适配器可以适配多个类,外观模式也可以只服务一个复杂的类.主要他们的意图是不一样的,

  • 适配器模式的意图是改变接口符合客户的预期
  • 外观模式的意图是提供子系统的一个简化接口.

参考《大话设计模式》 《Head First设计模式》

更多精彩内容关注公众号,和最有热心的小宇作者面对面 (可搜索: 呆呆熊一点通)

本文分享自微信公众号 - 呆呆熊的技术路(gh_93f28f51010a),作者:近视小猴子

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 设计模式第八讲-状态模式

    状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化.

    用户2825413
  • 设计模式第四讲--命令模式

    命令模式最初来源于图形化用户界面设计,但现在广泛应用于企业应用设计,特别促进了控制器(请求和分发处理)和领域模型(应用逻辑)的分离.说的更简单一点,命令模式有助...

    用户2825413
  • Elasticsearch-初识查询

    本小节主要讲述关于Elasticsearch的几种常见查询,希望自己在使用时候再回来看此文更能快速理解其中含义.

    用户2825413
  • java使用validator进行校验

    不管是html页面表单提交的对象数据还是和第三方公司进行接口对接,都需要对接收到的数据进行校验(非空、长度、格式等等)。如果使用if一个个进行校验(字段非常多)...

    小勇DW3
  • Guava-1.20类Splitter

    拆分字符串。 该类的实例是不可变的。构造方法对于引用的实例没有效果, 必须使用构造方法返回的splitter实例。

    悠扬前奏
  • Arrays.asList()使用指南

    最近使用Arrays.asList()遇到了一些坑,然后在网上看到这篇文章:Java Array to List Examples 感觉挺不错的,但是还不是特别...

    崔笑颜
  • tali -f 和 tail -F 之间的区别

    tail -f      等同于--follow=descriptor,根据文件描述符进行追踪,当文件改名或被删除,追踪停止

    xuyaowen
  • 纳税服务系统四(角色模块)【角色与权限、角色与用户】

    需求分析 我们直接来看看原型图,看看需求是怎么样的: ? 这里写图片描述 ? 这里写图片描述 我们看到上图,就会发现角色模块主要还是CRUD,唯一不同的就是它不...

    Java3y
  • 效率提高 10 倍 !一份不可多得的 Lombok 学习指南

    Lombok 是一款 Java 开发插件,使得 Java 开发者可以通过其定义的一些注解来消除业务工程中冗长和繁琐的代码,尤其对于简单的 Java 模型对象(P...

    黄泽杰
  • 一份不可多得的 Lombok 学习指南

    Lombok 是一款 Java 开发插件,使得 Java 开发者可以通过其定义的一些注解来消除业务工程中冗长和繁琐的代码,尤其对于简单的 Java 模型对象(P...

    阿宝哥

扫码关注云+社区

领取腾讯云代金券