前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >趣解设计模式之《为什么租房子要找中介?》

趣解设计模式之《为什么租房子要找中介?》

作者头像
爪哇缪斯
发布于 2023-10-06 04:38:47
发布于 2023-10-06 04:38:47
17800
代码可运行
举报
文章被收录于专栏:爪哇缪斯爪哇缪斯
运行总次数:0
代码可运行

〇、小故事

小王大学毕业了,打算来北京闯荡一下,于是就先寄宿到了他的表姐家,白天的时候,自己在外面小区转一转,看看能不能找到可以租到的房子,他找了好几天都没有找到合适的,要么就是小区里一张租房子的广告都没有,好不容易找到几个,里面的房间大小和价格又不合适。北京实在是太大了,而且这边人生地不熟的,找房子真的是耗费了他大量的力气。

到了周末,表姐问他这几天都在干嘛,他告诉了表姐自己找房子的经历,表姐跟他说,明天姐带你去找中介,这个事儿好办。第二天,小王和表姐到了某中介公司,跟中介表明自己需要寻找什么样的房子——主卧还是次卧屋子面积多少平米是否向阳房子在哪个区域内押金是多少…… 根据这些条件,中介给小王列出了好几个房源,然后就带着他们去看房,很快小王就找到了自己心仪的房子了

那么,上面的故事也是很多北漂人比较熟悉的经历吧。那么,对于房东和租客来说,中介人员就属于一个中间层,房东们与中介联系,将自己待出租的房子录入中介系统中,而访客又会通过中介去找房子,对于房子信息的采集,归类,降价,涨价,下架,匹配……这一系列工作都由中介人员去做,这样既使得房东很轻松,不用一次次对接房客,一遍遍的介绍自己的房子;也使得房客很轻松,直接通过中介系统就可以过滤出符合自己的房子,然后直奔目标,不用像个无头苍蝇一般的在各个小区乱碰运气的找房子。那么这个就是我们今天要介绍的设计模式——中介者模式

一、模式定义

中介者模式Mediator Pattern

使用中介者模式来集中相关对象之间复杂的沟通和控制方式。

为了便于理解,我们再举一个系统设计上的例子。在网上售卖商城的系统中,存在三个功能,分别为采购功能销售功能库存功能

采购功能】需要从销售功能获取到销售情况,并且确定是否要继续采购增加库存量。 【销售功能】要获得库存信息,并且销售量大于库存量,则需要通知采购功能快速采购商品。并且每当销售了产品后,需要扣减库存。 【库存功能】如果库存压力大了,要提示销售功能去折价促销,尽快消耗库存,并且通知采购功能暂时不要进行该商品的采购行为。

通过上面的描述,我们应该可以看到,采购销售库存这三个业务域是互相依赖的,如下图所示:

那么如果依照这种关联关系进行开发的话,就会出现这三个功能相互耦合的情况。如果需求变更了,会产生牵一发而动全身的情况发生。无形之中增加了业务开发量。那么针对这种情况,我们可以采取中介者模式或者叫做调停者模式。如下所示:

根据最小知识原则,无论是采购、销售还是库存,在他们眼中,最亲密的朋友都是这个中介者。而中介者将所有的业务逻辑关系进行整合,只需要这三个业务域提供针对他们自己业务的操作接口接口,后续如果需求变更,大概率涉及到修改的也都是在中介者

二、模式类图

针对上面讲的网上售卖商城例子,我们来画一下类的关系图。首先,创建3个类分别为Purchase采购人员)、Sale销售人员)和Stock库存人员),其次,创建一个抽象的同事类AbstractColleague,让刚刚创建的这3种人员都继承这个抽象类,该抽象类没有抽象方法需要子类实现,只是禁止本类被实例化成对象。在该抽象类中,引用了一个中介者类Mediator,该类引用了Purchase、Sale和Stock这三种工作人员,并且把他们的调用逻辑抽取出来放到中介者类中。请见下图所示:

三、代码实现

创建抽象同事类,并引用中介者Mediator的实例对象AbstractColleague.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class AbstractColleague {
    protected Mediator mediator;
    public AbstractColleague(Mediator mediator) {
        this.mediator = mediator;
    }
}

创建采购人员Purchase.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Purchase extends AbstractColleague {
    public Purchase(Mediator mediator) {
        super(mediator);
    }

    /** 采购电脑 */
    public void buyComputer(int num) {
        System.out.println();
        super.mediator.purchaseByComputer(num);
    }

    /** 不再采购电脑 */
    public void refuseBuyComputer() {
        System.out.println("不再采购电脑!");
    }
}

创建销售人员Sale.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Sale extends AbstractColleague {
    public Sale(Mediator mediator) {
        super(mediator);
    }

    /** 销售电脑 */
    public void sellComputer(int number) {
        super.mediator.saleSellComputer(number);
        System.out.println("销售电脑" + number + "台");
    }

    /** 获得销售情况(即:售卖了多少台电脑) */
    public int getSaleStatus() {
        // 模拟销售数量
        int sellNumber = new Random(System.currentTimeMillis()).nextInt(100);
        System.out.println("电脑的销售情况为:" + sellNumber + "台");
        return sellNumber;
    }

    /** 折价处理 */
    public void offSale() {
        super.mediator.saleOffSale();
    }
}

创建库存人员Stock.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Stock extends AbstractColleague {
    private static int COMPUTER_NUM = 100;

    public Stock(Mediator mediator) {
        super(mediator);
    }

    /** 增加库存 */
    public void increaseComputer(int number) {
        COMPUTER_NUM += number;
        System.out.println("电脑的库存数量为:" + COMPUTER_NUM);
    }

    /** 减少库存 */
    public void decreaseComputer(int number) {
        COMPUTER_NUM -= number;
        System.out.println("电脑的库存数量为:" + COMPUTER_NUM);
    }

    /** 获得当前库存 */
    public int getStockNumber() {
        return COMPUTER_NUM;
    }

    /** 清理库存 */
    public void clearStock() {
        System.out.println("清理库存数量为:" + COMPUTER_NUM);
        super.mediator.stockClear();
    }
}

创建中介者Mediator.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Mediator {
    protected Purchase purchase; // 采购人员
    protected Sale sale; // 销售人员
    protected Stock stock; // 库存人员

    public Mediator() {
        purchase = new Purchase(this);
        sale = new Sale(this);
        stock = new Stock(this);
    }

    /** 采购电脑 */
    public void purchaseByComputer(int num) {
        int saleStatus = sale.getSaleStatus();
        // 如果销售情况不好(即:没有超过80台),则采购总数减半
        String msg = "";
        if (saleStatus <= 80) {
            num = num / 2;
            msg = "由于销售不佳,采购总数减半,";
        }
        System.out.println(msg + "原有库存电脑" + stock.getStockNumber() + "台,现采购电脑" + num + "台");
        stock.increaseComputer(num);
    }

    /** 销售电脑 */
    public void saleSellComputer(int num) {
        // 如果库存数量不足,则采购2倍的num电脑数,暂时只售卖库存中有的数量
        int stockNum;
        if ((stockNum = stock.getStockNumber()) < num) {
            purchase.buyComputer(2*num);
            num = stockNum;
        }
        stock.decreaseComputer(num);
    }

    /** 折价销售电脑 */
    public void saleOffSale() {
        System.out.println("折价销售电脑");
    }

    /** 清理库存 */
    public void stockClear() {
        sale.offSale(); // 折价销售电脑
        purchase.refuseBuyComputer(); // 不要采购电脑
    }
}

创建测试类MediatorTest.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MediatorTest {
    public static void main(String[] args) {
        Mediator mediator = new Mediator();
        System.out.println("--------采购人员采购电脑--------");
        Purchase purchase = new Purchase(mediator);
        purchase.buyComputer(100);

        System.out.println("--------销售人员销售电脑--------");
        Sale sale = new Sale(mediator);
        sale.sellComputer(1);

        System.out.println("--------库房人员清库处理--------");
        Stock stock = new Stock(mediator);
        stock.clearStock();
    }
}

执行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
--------采购人员采购电脑--------

电脑的销售情况为:36台
由于销售不佳,采购总数减半,原有库存电脑100台,现采购电脑50台
电脑的库存数量为:150
--------销售人员销售电脑--------
电脑的库存数量为:149
销售电脑1--------库房人员清库处理--------
清理库存数量为:149
折价销售电脑
不再采购电脑!

Process finished with exit code 0

往期推荐

趣解设计模式之《做个Rapper咋这么难?》

(五)Kafka系列:一文了解Kafka的消息收集器RecordAccumulator

我想吃煎饼果子了~

(四)Kafka系列:连Producer端的主线程模块运行原理都不清楚,就敢说自己精通Kafka?

我发誓!再也不买一体机了!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-09-30 10:00,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爪哇缪斯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Flink1.4 执行计划
根据各种参数(如数据大小或集群中的机器数量),Flink的优化器自动会为你的程序选择一个执行策略。很多情况下,准确的知道Flink如何执行你的程序是很有帮助的。
smartsi
2019/08/07
5940
【Flink】基于 Flink 实时计算商品订单流失量
第三条规则可以理解为数据流去重,我在上一节已经介绍过了。为了更加专注于计算商品的订单流失量,本篇文章不再关注数据去重。
阿泽 Crz
2020/09/28
1.7K0
Flink Scala Shell:使用交互式编程环境学习和调试Flink
当前最著名的交互式编程环境莫属Jupyter Notebook了,程序员可以启动一个交互的Session,在这Session中编写代码、执行程序、获取结果,所见即所得。
PP鲁
2019/12/26
2.3K0
MYSQL高级篇-----索引优化分析
由于有些mysql不能使用full join,不过可以换种方法表示 A 的独有 + AB 共有 + B的独有 union本身就可以去重 所以可以这样使用
默 语
2024/11/20
5870
MYSQL高级篇-----索引优化分析
两个案例带你看懂YashanDB执行计划
执行计划是数据库查询优化的基石。学习阅读执行计划有助于深入了解数据库对SQL查询的解析和执行机制。执行计划揭示了查询的逻辑流程,包括表连接方式、数据过滤和聚合方法以及结果排序规则,这对于诊断性能瓶颈、优化查询速度和提高资源利用率至关重要。开发人员可以通过分析执行计划,识别索引使用的有效性,确定是否需要调整查询结构,以及是否需要更新数据库统计信息,从而编写更高效的SQL代码,提升数据库性能,确保数据检索兼具速率与成本效益。
用户11512874
2025/02/19
1380
MySQL中的执行计划
​ 一条查询语句在经过MySQL查询优化器的各种基于成本和规则的优化会后生成一个所谓的执行计划,这个执行计划展示了接下来具体执行查询的方式,比如多表连接的顺序是什么,对于每个表采用什么访问方法来具体执行查询等等。
俺也想起舞
2021/10/26
8930
如果面试官让你讲讲发布订阅设计模式?
有小伙伴问,该如何学习设计模式,设计模式本身是一些问题场景的抽象解决方案,死记硬背肯定不行,无异于搭建空中楼阁,所以得结合实际,从解决问题角度去思考、举一反三,如此便能更轻松掌握知识点。
小东同学
2022/07/29
2.7K0
如果面试官让你讲讲发布订阅设计模式?
【Apache Doris】周FAQ集锦:第 13 期
在这个栏目中,每周将筛选社区反馈的热门问题和话题,重点回答并进行深入探讨。旨在为广大用户和开发者分享有关 Apache Doris 的常见问题。
一臻数据
2024/12/24
1140
【Apache Doris】周FAQ集锦:第 13 期
Flink CEP 新特性进展与在实时风控场景的落地
摘要:本文整理自阿里云开发工程师耿飙&阿里云开发工程师胡俊涛,在 FFA 实时风控专场的分享。本篇内容主要分为四个部分:
从大数据到人工智能
2023/02/13
2.4K0
Flink CEP 新特性进展与在实时风控场景的落地
SparkSQL快速入门系列(6)
上一篇《SparkCore快速入门系列(5)》,下面给大家更新一篇SparkSQL入门级的讲解。
刘浩的BigDataPath
2021/04/13
2.4K0
SparkSQL快速入门系列(6)
幻兽帕鲁Palworld服务器搭建教学
幻兽帕鲁最近在社区呈现了爆火的趋势,在线人数已突破百万级别,官方服务器也开始出现不稳定,卡人闪退的情况。对于有一定财力的小伙伴,搭建一个私人服务器是一个最稳定而
黄杨峻
2024/01/22
45.7K58
幻兽帕鲁Palworld服务器搭建教学
SQL优化
1.MySQL版本: 5.x: 5.0-5.1:早期产品的延续,升级维护 5.4 - 5.x : MySQL整合了三方公司的新存储引擎 (推荐5.5)
友儿
2022/09/09
1.8K0
SQL优化全套笔记
1.MySQL版本: 5.x: 5.0-5.1:早期产品的延续,升级维护 5.4 - 5.x : MySQL整合了三方公司的新存储引擎 (推荐5.5) 安装:rpm -ivh rpm软件名 如果安装时 与某个软件 xxx冲突,则需要将冲突的软件卸载掉: yun -y remove xxx 安装时 有日志提示我们可以修改密码:/usr/bin/mysqladmin -u root password ‘new-password’
葆宁
2019/04/19
8540
Flink SQL 知其所以然(二十五):基础 DML SQL 执行语义!
以下面的 SQL 为例,我们来介绍下其在离线中和在实时中执行的区别,对比学习一下,大家就比较清楚了
公众号:大数据羊说
2022/07/07
8600
Flink SQL 知其所以然(二十五):基础 DML SQL 执行语义!
【答案&解析】Java工程师100道考题 | 超过60分的不到10%!
小傅哥,你的100道Java考题,我只考了16分,是不是没救了!给我个答案吧!那么鉴于不少小伙伴已经考完了,那么小傅哥就做一个考题解析,方便读者可以针对自己的问题进行补充学习。
小傅哥
2022/12/13
2.5K0
【答案&解析】Java工程师100道考题 | 超过60分的不到10%!
大数据技术之_27_电商平台数据分析项目_02_预备知识 + Scala + Spark Core + Spark SQL + Spark Streaming + Java 对象池
List 元素的追加 方式1-在列表的最后增加数据 方式2-在列表的最前面增加数据
黑泽君
2019/06/14
2.8K0
大数据技术之_27_电商平台数据分析项目_02_预备知识 + Scala + Spark Core + Spark SQL + Spark Streaming + Java 对象池
2024年最新Flink教程,从基础到就业,大家一起学习--flink部署和集群部署(从本地测试到公司生产环境如何部署项目源码)
这些内容都是自己一边学习一边总结的,其中每一个知识点都是经过翻阅大量资料整理,包含一些常见的报错和报警都会详细的举例和说明,大家一起学习。
小白的大数据之旅
2024/11/20
3400
2024年最新Flink教程,从基础到就业,大家一起学习--flink部署和集群部署(从本地测试到公司生产环境如何部署项目源码)
读Flink源码谈设计:图的抽象与分层
前阵子组里的小伙伴问我“为什么Flink从我们的代码到真正可执行的状态,要经过这么多个graph转换?这样做有什么好处嘛?”我早期看到这里的设计时的确有过相同的疑惑,当时由于手里还在看别的东西,查阅过一些资料后就翻页了。如今又碰到了这样的问题,不妨就在这篇文章中好好搞清楚。
泊浮目
2023/12/27
2470
Flink
  1)Flink 是标准的实时处理引擎,基于事件驱动。而 Spark Streaming 是微批(Micro-Batch)的模型;
挽风
2023/10/17
5730
Flink
Flink面试通关手册「160题升级版」
主要是当Flink开启Checkpoint的时候,会往Source端插入一条barrir,然后这个barrir随着数据流向一直流动,当流入到一个算子的时候,这个算子就开始制作checkpoint,制作的是从barrir来到之前的时候当前算子的状态,将状态写入状态后端当中。然后将barrir往下流动,当流动到keyby 或者shuffle算子的时候,例如当一个算子的数据,依赖于多个流的时候,这个时候会有barrir对齐,也就是当所有的barrir都来到这个算子的时候进行制作checkpoint,依次进行流动,当流动到sink算子的时候,并且sink算子也制作完成checkpoint会向jobmanager 报告 checkpoint n 制作完成。
大数据真好玩
2021/07/07
2.8K0
推荐阅读
相关推荐
Flink1.4 执行计划
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档