Java设计模式-设计模式-中介者模式

Java设计模式-中介者模式(Mediator Pattern)

目录

  • 什么是中介者模式
  • 中介者的实现方式
  • JavaSE中介者模式的应用
  • Struts2中介者模式的应用

中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。

一、什么是中介者模式

使用中介对象来封装和处理多个对象之间的关联关系,降低多个对象之间的耦合度,使1对多变为1对1的耦合状态。例如机场调度,每个国家之间的飞机只需要与机场沟通即可,无需和各个国家的飞机沟通;MVC框架中C(控制器)就是 M(模型)和 V(视图)的中介者,负责协调M与V

中介者模式降低了类的复杂度,将一对多转化成了一对一关系, 降低了各个类之间的耦合度,符合迪米特原则。

二、中介者模式的实现方式

先讲一下如果不使用中介模式,对象直接的关系是什么样的,下面的代码案例是房屋拍卖,分别是房屋所有者、买家A、买家B,最终根据AB的价格,卖家决定是否出售

package org.MediatorPatttern.version2;

class HouseOwner {
    // 原始价格
    private static int price = 200;

    // 当前价格
    public void setPrice(int p){
        this.price = p;
    }

    public boolean sell(){
        BuyerA buyerA = new BuyerA();
        BuyerB buyerB = new BuyerB();
        // 如果有一方退出,则停止
        if (!buyerA.getStatus() || !buyerB.getStatus()){
            String buyer = (buyerA.getPrice() > buyerB.getPrice())?"买家A":"买家B";

            System.out.println("买家A最终出价:" + buyerA.getPrice() + " , " + "买家B最终出价:" + buyerB.getPrice() + "最终买家为:" + buyer);
            return true;
        }
        return false;
    }

}

class BuyerA{
    // 是否继续加价
    private static boolean state = true;
    //每次加价
    private static int price_ev = 10;
    // 最高出价
    private static int PRICE = 260;
    // 当前出价
    private static int now_price = 200;
    
    public void givePrice(){
        HouseOwner houseOwner = new HouseOwner();
        BuyerB buyerB = new BuyerB();

        if(now_price >= PRICE || !buyerB.getStatus()){
            // 如果大于心里低价,就不买了
            this.giveUp();
        }else {
            // 加价一次
            now_price = now_price + price_ev;
            houseOwner.setPrice(now_price);
            System.out.println("买家A出价" + now_price);

        }

    }
    public int getPrice(){
        return now_price;
    }
    public void giveUp(){
        this.state = false;
    }
    public boolean getStatus(){
        return this.state;
    }

}
class BuyerB{
    // 是否继续加价
    private static boolean state = true;
    //每次加价
    private static int price_ev = 20;
    // 最高出价
    private static int PRICE = 280;
    // 当前出价
    private static int now_price = 200;

    public void givePrice(){
        HouseOwner houseOwner = new HouseOwner();
        BuyerA buyerA = new BuyerA();

        // 如果现在的出价低于我的心里价就继续出价,如果现在的出价是大于买家A的价格也继续出价
        if(now_price >= PRICE || !buyerA.getStatus()){

            // 如果大于心里低价,就不买了
            this.giveUp();
        }else {
            // 加价一次
            now_price = now_price + price_ev;
            houseOwner.setPrice(now_price);
            System.out.println("买家B出价" + now_price);
            // 如果小于当前心理价,就继续出价
        }

    }
    public int getPrice(){
        return now_price;
    }
    public void giveUp(){
        this.state = false;
    }
    public boolean getStatus(){
        return this.state;
    }

}

public class NoMediator {
    public static void main(String[] args) {
        HouseOwner houseOwner = new HouseOwner();
        BuyerA buyerA = new BuyerA();
        BuyerB buyerB = new BuyerB();
        boolean status = false;
        while (true){
            buyerA.givePrice();
            buyerB.givePrice();
            status = houseOwner.sell();
            if (status){
                return;
            }
        }
    }
}
// 运行结果
买家A出价210
买家B出价220
买家A出价220
买家B出价240
买家A出价230
买家B出价260
买家A出价240
买家B出价280
买家A出价250
买家A最终出价:250 , 买家B最终出价:280最终买家为:买家B

可以看出在BuyerA、BuyerB的givePrice()方法中都使用了另外两个对象,HouseOwner的sell方法也使用了BuyerA、BuyerB对象,这三个类互相引用导致关系极为复杂,当BuyerA类修改时,另外两个类都要改变,这不是我们想要的,耦合太严重了。

看看如何使用中介者模式来处理房屋买卖的问题,分别有买家A、B、房主、中介,买家只与中介联系,中介负责买家和房主的沟通

package org.MediatorPatttern.version3;

/**
 * 中介抽象类
 */
abstract class Mediator{
    public static boolean status = false;
    public HouseOwner houseOwner;
    public Mediator(HouseOwner houseOwner){
        this.houseOwner = houseOwner;
    }
    public abstract int contact();
    // 讲价
    public abstract boolean bargain(Tenant tenant);

}

/**
 * 中介实现类
 */
class ConcreteMediator extends Mediator{

    public ConcreteMediator(HouseOwner houseOwner) {
        super(houseOwner);
    }

    // 买家联系中介,看是否有房子
    @Override
    public int contact() {
        int p = houseOwner.getPrice();
        System.out.println("我这里有房子,房主出价:" + p);
        return p;
    }

    // 与传进来的买件讨价还价
    @Override
    public boolean bargain(Tenant tenant) {
        int tenant_p = tenant.getPrice();
        if ( tenant_p >= houseOwner.getSale_price()){
            System.out.println("房主说可以," + tenant_p +"成交");
            status = true;
            return true;
        }
        System.out.println("房主不同意,价格太低,最低价"+ houseOwner.getSale_price());
        return false;
    }

}

/**
 * 房主
 */
class HouseOwner{
    // 挂牌价
    private final int price = 200;
    // 底价
    private final int sale_price = 190;

    public int getPrice() {
        return price;
    }
    public int getSale_price(){
        return sale_price;
    }

}
interface Tenant {

    public int getPrice();
    public int givePrice();


}

class ConcreteTenantA implements Tenant{
    // 第一次出价
    int price = 160;
    // 每次加价10万
    int step = 10;

    @Override
    public int getPrice() {
        return this.price;
    }

    @Override
    public int givePrice() {
        this.price += this.step;
        System.out.println("买家A出价" + this.getPrice());
        return this.getPrice();
    }
}

class ConcreteTenantB implements Tenant{
    // 第一次出价
    int price = 170;
    // 每次加价5万
    int step = 5;

    @Override
    public int getPrice() {
        return this.price;
    }

    @Override
    public int givePrice() {
        this.price += this.step;
        System.out.println("买家B出价" + this.getPrice());
        return this.getPrice();
    }
}

public class TestMediator {
    public static void main(String[] args) {
        ConcreteTenantA concreteTenantA = new ConcreteTenantA();
        ConcreteTenantB concreteTenantB = new ConcreteTenantB();
        HouseOwner houseOwner = new HouseOwner();
        Mediator mediator = new ConcreteMediator(houseOwner);

        System.out.println("买家A、B想买房");
        mediator.contact();
        boolean status;
        while (true){
            // 买家A出价
            concreteTenantA.givePrice();
            // 中介联系房主
            status = mediator.bargain(concreteTenantA);
            // 如果房主同意就买
            if(status)return;

            // 买家B出价
            concreteTenantB.givePrice();
            mediator.bargain(concreteTenantA);
            if(status)return;

        }

    }
}
// 运行结果如下
买家A、B想买房
我这里有房子,房主出价:200
买家A出价170
房主不同意,价格太低,最低价190
买家B出价175
房主不同意,价格太低,最低价190
买家A出价180
房主不同意,价格太低,最低价190
买家B出价180
房主不同意,价格太低,最低价190
买家A出价190
房主说可以,190成交

可以看出买家A、B、房主都是只与中介联系,买家之间、买家与房主之间都没有任何联系,实现类与类之间的解耦,在真实场景中买家之间也是互相不知道出价。由此可见中介者模式的

优点是

  1. 将网状结构的对象关系,变为星型
  2. 减少类之间的依赖,实现解耦,符合迪米特法则

缺点是

  1. 中介者承担较多责任,随着业务复杂度增加,中介者类会变得难以维护

分析下中介者模式的构成

  • 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。–Mediator
  • 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。–ConcreteMediator
  • 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。–Tenant
  • 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。–ConcreteTenantA、ConcreteTenantB

三、JavaSE中介者模式的应用

Timer 可以按计划执行重复的任务或者定时执行指定任务,这是因为 Timer 内部利用了一个后台线程 TimerThread 有计划地执行指定任务。

  • Timer:是一个实用工具类,该类用来调度一个线程(schedule a thread) ,使它可以在将来某一时刻执行。Java 的 Timer 类可以调度一个任务运行一次或定期循环运行。 Timer tasks should complete quickly,即定时器中的操作要尽可能花费短的时间。
  • TimerTask:一个抽象类,它实现了 Runnable 接口。我们需要扩展该类以便创建自己的 TimerTask,这个 TimerTask 可以被 Timer 调度。

一个 Timer 对象对应的是单个后台线程,其内部维护了一个 TaskQueue,用于顺序执行定时器任务 TimeTask。

即:Timer 是定时器,TimerTask 是定时器任务。Timer的每个schedule方法都调用了sched方法。

分析下中介者模式的构成

  • 抽象中介者(Mediator)角色:无
  • 具体中介者(ConcreteMediator)角色:Timer
  • 抽象同事类(Colleague)角色:Runnable
  • 具体同事类(Concrete Colleague)角色:TimerTask

四、Struts2中介者模式的应用

MVC的模式倒是使用了中介者模式,但在其它的具体代码中未发现中介者模式的应用,读者如果有发现可以联系我补充,谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MarginSelf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值