设计模式第六讲-外观模式

栏目: 后端 · 发布时间: 5年前

内容简介:外观模式(Facade,门面模式), 为子系统中额外一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。在项目开发和实际运用中十分频繁,但是其极易理解图例:

外观模式(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设计模式》

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

设计模式第六讲-外观模式

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First jQuery

Head First jQuery

Ryan Benedetti , Ronan Cranley / O'Reilly Media / 2011-9 / USD 39.99

Want to add more interactivity and polish to your websites? Discover how jQuery can help you build complex scripting functionality in just a few lines of code. With Head First jQuery, you'll quickly g......一起来看看 《Head First jQuery》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具