行百里er 行百里er
首页
  • 分类
  • 标签
  • 归档
设计模式
  • JVM
  • Java基础
MySQL
Elastic Stack
Redis
  • Kafka
  • RocketMQ
分布式
Spring Cloud Alibaba
云原生
数据结构与算法
关于
GitHub (opens new window)

行百里er

Java程序员一枚
首页
  • 分类
  • 标签
  • 归档
设计模式
  • JVM
  • Java基础
MySQL
Elastic Stack
Redis
  • Kafka
  • RocketMQ
分布式
Spring Cloud Alibaba
云原生
数据结构与算法
关于
GitHub (opens new window)
  • 【设计模式】各个击破单例模式的8种写法
  • 【设计模式】策略模式之“这不就是if-else吗”
  • 【设计模式】工厂系列-FactoryMethod,AbstractFactory,Spring IOC
  • 【设计模式】只需体验三分钟,你就会跟我一样了解Facade和Mediator模式
    • Facade 门面模式
      • 模拟场景
      • 代码模拟
      • 用门面模式解决这一疑难杂症
      • 似曾相识的Facade
    • Mediator 调停者模式
      • 张三的烦恼
      • 模拟现场
      • 消息中间件
      • 调停者模式的优缺点
  • 【设计模式】代理模式那些事儿:静态代理,动态代理,JDK的动态代理,cglib,Spring AOP
  • 【设计模式】通俗易懂版责任链模式
  • 【设计模式】模板模式,学会它咱也写出优雅健壮的代码!
  • 【设计模式】好玩的原型模式:Prototype
  • 【设计模式】1分钟整明白什么是Builder建造者模式
  • 设计模式
行百里er
2020-08-08
目录

【设计模式】只需体验三分钟,你就会跟我一样了解Facade和Mediator模式

作者:行百里er

博客:https://chendapeng.cn (opens new window)

提示

这里是 行百里er 的博客:行百里者半九十,凡事善始善终,吾将上下而求索!

# Facade 门面模式

# 模拟场景

现有Client一枚,需要在城里落户,要转户口,现在有关部门要求Client准备一系列的材料。

我们精简一下部门,假设只需要跑材料部门、核验盖章部门和制证发证部门三个部门就行了。

现在需要Client先去材料部门领取材料,然后填写完成后到核验部门盖章,最后拿着盖着的材料去制证部门领证,这样一套按照顺序走下来,业务才能算完成。

# 代码模拟

材料部门

/**
 * 材料部门,给办证者提供必要的材料
 * @author 行百里者
 */
public class StuffDept {
    public void makeStuff() {
        //处理业务逻辑
        System.out.println("制作相关材料,并发给Client填写");
    }
}
1
2
3
4
5
6
7
8
9
10

盖章部门

/**
 * 检查核验部门,核验通过才给盖章
 * @author 行百里者
 */
public class CheckDept {
    public void checkStuff() {
        //处理业务逻辑
        System.out.println("核查材料的准确性,核查通过才给盖章");
    }
}
1
2
3
4
5
6
7
8
9
10

制证部门

/**
 * 发证部门
 * @author 行百里者
 */
public class IssueDept {
    public void issueCert() {
        //处理业务逻辑
        System.out.println("发证部门检验材料是否盖章,然后制证发证");
    }
}
1
2
3
4
5
6
7
8
9
10

需要办证的Client处理场景:

public class Client {
    public static void main(String[] args) {
        //一定要按照这个顺序去办证,否则拿不到证
        StuffDept sd = new StuffDept();
        sd.makeStuff();
        CheckDept cd = new CheckDept();
        cd.checkStuff();
        IssueDept id = new IssueDept();
        id.issueCert();
    }
}
1
2
3
4
5
6
7
8
9
10
11

其实,现实生活中,我们可能远不止跑这三个部门,如果Client来回穿梭于N个部门间,办事效率是不是很垃圾了!

# 用门面模式解决这一疑难杂症

好在现在很多地方提供了网上通道办理一些业务,Client只需要跑一次就可以了,Client只需要和网上通道-NetApp打交道就可以了。

/**
 * “中国式办证”所需的“门面”部门,负责统一处理各部门的事情,
 * Client只需要调“门面”的doItJustOnce方法即可
 * @author 行百里者
 */
public class NetApp {
    private StuffDept stuffDept = new StuffDept();
    private CheckDept checkDept = new CheckDept();
    private IssueDept issueDept = new IssueDept();
    
    public void doItJustOnce() {
        stuffDept.makeStuff();
        checkDept.checkStuff();
        issueDept.issueCert();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Client调起

public class Client {
    public static void main(String[] args) {
        NetApp facade = new NetApp();
        facade.doItJustOnce();
    }
}
1
2
3
4
5
6

对于Client来说,是不是就清爽了!

这不就是再封装了一层吗?没错,这就是 门面模式 ,解决了Client向各个部门内部调用,并且按照指定的顺序调用这一繁琐的问题。

# 似曾相识的Facade

支付宝支付API

接入方只管调用,不管它的内部怎样实现的,只需要根据其开放的API进行数据交互。

支付宝开放API就可以理解为是Facade模式的应用。

日志框架SLF4J

SLF4J 日志框架采用的就是门面设计模式,对外隐藏系统内部的复杂性,并向外部调用的客户端或程序提供统一的接口。

private static final Logger LOGGER = LoggerFactory.getLogger(Provider.class);

public String doSomething() {
    LOGGER.info("service name:{}", serviceName);
}
1
2
3
4
5

一句话就可以直接输出日志信息,而不管其内部是Log4j实现的还是logback实现的,用起来就是简单明了。

JDBC数据库操作

数据库JDBC的操作,例如:

@Component
public class DBUtil {

    private static String URL;

    private static String DRIVER;

    private static String USERNAME;

    private static String PASSWORD;

    private static Connection connection = null;

    private static final Logger LOGGER = LoggerFactory.getLogger(DBUtil.class);


    /**
     * 获取JDBC连接
     *
     */
    public static Connection getConnection() {
        try {
            //加载驱动程序:它通过反射创建一个driver对象。
            Class.forName(DRIVER);

            //获得数据连接对象。
            connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            return connection;
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("获取JDBC连接异常, {}", e.getMessage());
        }
        return null;
    }

    @Value("${db.dburl}")
    public void setURL(String dburl) {
        URL = dburl;
    }

    @Value("${db.dbdriver}")
    public void setDRIVER(String dbdriver) {
        DRIVER = dbdriver;
    }

    @Value("${db.dbusername}")
    public void setUSERNAME(String dbusername) {
        USERNAME = dbusername;
    }

    @Value("${db.dbpassword}")
    public void setPASSWORD(String dbpassword) {
        PASSWORD = dbpassword;
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

获取数据库连接的时候,只需要传入driver的驱动类名称即可,如果以后我们更换Class.forName中的 driver 非常方便,比如从MySQL数据库换到Oracle数据库,只要更换facade中的driver就可以。

# Mediator 调停者模式

有的地方把它叫做中介者模式,名字不重要!!!

# 张三的烦恼

张三的老婆发现他最近有点异常,怀疑张三和他前女友藕断丝连,于是张老婆去找张三他妈评理,但是俩人很快吵起来了,此时小姑子出现了,又是一顿吵,是互相吵的那种。

张三恼了,和其他三人也吵起来了。

他很想结束现状,但是他已无能为力,甚至自己也陷入其中,要是居委会大妈在就好了!!!

居委会大妈的职责就是协调他们内部的事情,有什么事直接跟我说,保证把你们的事情都解决!!!

居委会大妈就是调停者,中介者。

# 模拟现场

调停者

加入了一个中介者作为四个模块的交流核心,每个模块之间不再相互交流,要交流就通过中介者居委会大妈进行。每个模块只负责自己的业务逻辑,不属于自己的则丢给中介者来处理,简化了各模块之间的耦合关系。

# 消息中间件

卧槽,中介处理各个模块的需求,而且各个模块之间不需要通信,消息中间件不就是这种模式吗?

对!MQ就可以理解为Mediator模式。

# 调停者模式的优缺点

  • 优点

中介者模式的优点就是减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,减少了依赖,当然同时也降低了类间的耦合。

  • 缺点

中介者模式的缺点就是中介者会膨胀得很大,而且逻辑复杂,,中介者的逻辑就越复杂。

好了,你已经会门面模式和调停者模式了。下一个!!!


首发公众号 行百里er ,欢迎老铁们关注阅读指正。

首发公众号 行百里er ,欢迎老铁们关注阅读指正。代码仓库 GitHub github.com/ChenDapengJava (opens new window)

#设计模式
上次更新: 2022/10/06, 18:00:06
【设计模式】工厂系列-FactoryMethod,AbstractFactory,Spring IOC
【设计模式】代理模式那些事儿:静态代理,动态代理,JDK的动态代理,cglib,Spring AOP

← 【设计模式】工厂系列-FactoryMethod,AbstractFactory,Spring IOC 【设计模式】代理模式那些事儿:静态代理,动态代理,JDK的动态代理,cglib,Spring AOP→

最近更新
01
重要数据不能丢!MySQL数据库定期备份保驾护航!
05-22
02
分布式事务解决方案之 Seata(二):Seata AT 模式
09-09
03
Seata 番外篇:使用 docker-compose 部署 Seata Server(TC)及 K8S 部署 Seata 高可用
09-05
更多文章>
Theme by Vdoing | Copyright © 2020-2023 行百里er | MIT License | 豫ICP备2022020385号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式