红绿灯与调停者模式

生活中的例子

        我们每天都会过马路,当十字路口有红绿灯时,我们只需要等绿灯亮就可以安心的走了。但是如果没有红绿灯,我们在过马路时就需要仔细多了。我们需要不停的观察路上行驶的车辆,小心谨慎的走,直到穿过马路。
        将上面的例子类比到代码的世界里,不管是人还是车辆都可以算作是对象。当这些对象要穿过十字路口时,如果没有红绿灯,那就需要彼此引用,不断的判断彼此的状态,这样就相当复杂了。但是如果有了红绿灯就不一样了。当有了红绿灯后,车辆、行人就不需要观察彼此的状态了。大家都看红绿灯即可,红灯停绿灯行。
        在这个例子中,红绿灯就是一个调停者

调停者说明

调停者模式包装了一系列对象相互作用的方式,使得这些对象不必明显引用。从而使他们可以比较松散的耦合,而且可以独立的改变他们之间的交互。

代码样例

接下来,我们通过代码来看看调停者模式是如何工作的

网上很多调停者都是用在UI组件或者聊天室的demo中的

首先我们定义调停者,也就是红绿灯

/**
 * 信号灯,调停者接口,方便替换调停者
 * @author skyline
 */
public interface SignalLamp {

    boolean canGo(Direction direction);
}

/**
 * 红绿灯,最最简单的那种红绿灯
 * @author skyline
 */
public class TrafficLights implements SignalLamp {
    /**
     * 状态,0红灯亮,东西方向的车不能走,1绿灯亮,东西方向的车可以走
     */
    private int status;

    /**
     * 状态,0红灯亮,东西方向的车不能走,1绿灯亮,东西方向的车可以走
     *
     * @param status
     */
    public void setStatus(int status) {
        this.status = status;
    }

    @Override
    public boolean canGo(Direction direction) {
        if (status == 1) {
            return direction == Direction.EW;
        } else {
            return direction == Direction.SN;
        }
    }

    @Override
    public String toString() {
        return "TrafficLights{" +
                "status=" + status +
                '}';
    }
}

然后我们定义路上的车辆

/**
 * 抽象汽车
 * @author skyline
 */
public abstract class Car {
    Direction direction;
    SignalLamp signalLamp;

    Car(Direction direction, SignalLamp signalLamp) {
        this.direction = direction;
        this.signalLamp = signalLamp;
    }

    public abstract void go();
}

/**
 * 公交车,汽车的一种
 * @author skyline
 */
public class Bus extends Car {

    Logger logger = LoggerFactory.getLogger(Bus.class);

    public Bus(Direction direction, SignalLamp signalLamp) {
        super(direction, signalLamp);
    }

    @Override
    public void go() {
        if (signalLamp.canGo(direction)) {
            logger.info("[{}]gogogo", this);
        } else {
            logger.info("[{}]can not go", this);
        }
    }

    @Override
    public String toString() {
        return "Bus{" +
                "direction=" + direction +
                ", signalLamp=" + signalLamp +
                "} ";
    }
}
/**
 * 小轿车,汽车的一种
 * @author skyline
 */
public class Sedan extends Car {

    Logger logger = LoggerFactory.getLogger(Sedan.class);

    public Sedan(Direction direction, SignalLamp signalLamp) {
        super(direction, signalLamp);
    }

    @Override
    public void go() {
        if (signalLamp.canGo(direction)) {
            logger.info("[{}]gogogo", this);
        } else {
            logger.info("[{}]can not go", this);
        }
    }

    @Override
    public String toString() {
        return "Sedan{" +
                "direction=" + direction +
                ", signalLamp=" + signalLamp +
                "} ";
    }
}
/**
 * 大卡车
 * @author skyline
 */
public class Truck extends Car {

    Logger logger = LoggerFactory.getLogger(Truck.class);

    public Truck(Direction direction, SignalLamp signalLamp) {
        super(direction, signalLamp);
    }

    @Override
    public void go() {
        if (signalLamp.canGo(direction)) {
            logger.info("[{}]gogogo", this);
        } else {
            logger.info("[{}]can not go", this);
        }
    }

    @Override
    public String toString() {
        return "Truck{" +
                "direction=" + direction +
                ", signalLamp=" + signalLamp +
                "} ";
    }
}

最后,我们看下Main方法

public class Main {
    public static void main(String[] args) {
        TrafficLights trafficLights = new TrafficLights();
        trafficLights.setStatus(0);
        Bus bus = new Bus(Direction.EW, trafficLights);
        Sedan sedan = new Sedan(Direction.SN, trafficLights);
        Truck truck = new Truck(Direction.EW, trafficLights);
        bus.go();
        sedan.go();
        truck.go();
    }
}

结果
在这里插入图片描述

总结

  1. 从Main方法的逻辑中可以看到,各个车辆之间行驶方向不同,但是都调用了go方法
  2. 具体能不能行驶由TrafficLights来进行判断
  3. 如果没有TrafficLights,那每辆车之间需要相互引用,然后再在go方法中判断各种可能的情况,判断后才能知道能不能行驶
  4. 调停者的引入简化了多个对象之间的关系,由原来的多对多简化为一对一
  5. 调停者模式并不是发布订阅,个人感觉调停者需要负责一定的业务逻辑,而发布订阅中的Message不需要执行业务逻辑
  6. 在上面的例子中,如果红绿灯换成那种有单独转向灯的信号灯,原有的车辆对象不需要修改,只需要替换TrafficLights就可以了。
  7. 这种设计模式需要谨慎使用,如果设计不当,调停者对象可能会演化为上帝对象,最终难以维护。
  8. 调停者模式的用途是管理很多对象的相互作用,以便这些对象可以专注于自身的行为,而独立于其他对象。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值