详解Java中介模式

详解Java中介模式

本文我们探讨GoF设计模式中的中介模式,详细说明其目的以及什么场景下使用。当然我会结合示例进行实战说明。

中介模式

面向对象编程中,我们始终应该让设计的系统组件保持松耦合并可重用。这会让我们代码更容易维护和测试。

实际应用中,我们经常需要处理复杂的对象之间依赖,这时中介模式就派上用场了。

中介模式的目的就是为了减少复杂性和依赖性,避免精密耦合对象之间直接通信。通过创建中介对象负责依赖对象之间的交互,因此,所有交互都通过中介对象实现。

这提升松耦合的可能,因为一组协同对象之间不再直接交互。相反它们依赖单个中介对象,这样增强了这些对象的课重用性。

中介模式的UML图

让我们先看下面uml图示:
在这里插入图片描述
在上面的uml途中,我们能识别下面一些参与者:

  • 定义Mediator接口用于 Colleague 对象直接交互
  • 定义抽象类Colleague,包括单个 Mediator引用
  • ConcreteMediator类封装Colleague 对象直接交互逻辑
  • ConcreteColleague1 和 ConcreteColleague2 仅通过 Mediator 进行交互

我们看到Colleague对象直接不相互直接引用,而是通过Mediator进行交互。因此,ConcreteColleague1 和 ConcreteColleague2可重用性增强。另外,当我们需要改变Colleague 对象直接的交互方式时,仅需修改ConcreteMediator 逻辑或创建一个新的Mediator实现。

Java 代码实现

到目前为止,我们有了清晰理念,下面我们通过代码更好理解其中概念。

示例场景

加入我们构建一个简单系统包括风扇、电源以及按钮。点击按钮能开启或关闭风扇。在我们开启风扇之前需先开电源;类似我们关闭风扇后需立刻关闭电源。

下面请看示例实现:

public class Button {
    private Fan fan;
 
    // constructor, getters and setters
 
    public void press(){
        if(fan.isOn()){
            fan.turnOff();
        } else {
            fan.turnOn();
        }
    }
}
public class Fan {
    private Button button;
    private PowerSupplier powerSupplier;
    private boolean isOn = false;
 
    // constructor, getters and setters
 
    public void turnOn() {
        powerSupplier.turnOn();
        isOn = true;
    }
 
    public void turnOff() {
        isOn = false;
        powerSupplier.turnOff();
    }
}
public class PowerSupplier {
    public void turnOn() {
        // implementation
    }
 
    public void turnOff() {
        // implementation
    }
}

测试功能的代码:

@Test
public void givenTurnedOffFan_whenPressingButtonTwice_fanShouldTurnOnAndOff() {
    assertFalse(fan.isOn());
 
    button.press();
    assertTrue(fan.isOn());
 
    button.press();
    assertFalse(fan.isOn());
}

不错,功能实现了。但我们注意到三个类紧紧耦合。Button直接操作Fan,Fan同时和Button和PowerSupplier交互。这样Button类很难再重用,同时如果需要增加第二个电源至我们系统总,那么必须要修改Fan类的逻辑。

增加中介模式

下面我们实现中介模式,减少类之间的依赖,使代码更好重用。首先看Mediator类:

public class Mediator {
    private Button button;
    private Fan fan;
    private PowerSupplier powerSupplier;
 
    // constructor, getters and setters
 
    public void press() {
        if (fan.isOn()) {
            fan.turnOff();
        } else {
            fan.turnOn();
        }
    }
 
    public void start() {
        powerSupplier.turnOn();
    }
 
    public void stop() {
        powerSupplier.turnOff();
    }
}

接下来修改其余类:

public class Button {
    private Mediator mediator;
 
    // constructor, getters and setters
 
    public void press() {
        mediator.press();
    }
}
public class Fan {
    private Mediator mediator;
    private boolean isOn = false;
 
    // constructor, getters and setters
 
    public void turnOn() {
        mediator.start();
        isOn = true;
    }
 
    public void turnOff() {
        isOn = false;
        mediator.stop();
    }
}

再次测试我们代码:

@Test
public void givenTurnedOffFan_whenPressingButtonTwice_fanShouldTurnOnAndOff() {
    assertFalse(fan.isOn());
  
    button.press();
    assertTrue(fan.isOn());
  
    button.press();
    assertFalse(fan.isOn());
}

ok,测试通过。到目前为止我们已经实现了中介模式,Button, Fan, PowerSupplier类之间不再直接交互,仅和Medator引用进行交互。

如果未来我们需要增加第二个电源,仅需要更新Medator逻辑,Button, Fan类保持不变。该示例很好说明了如何分离依赖对象使代码更易维护。

什么场景下使用中介模式

如果需要处理一组紧耦合对象、难维护的代码场景,适合使用中介模式。其减少对象之间依赖和总体的复杂度。

另外,通过使用中介模式,抽出交互逻辑至单个组件,遵循单一责任原则。而且引入新的中介对象,无需修改其余对象,符合开放-闭合原则。

然而有时因为错误的设计有很多紧耦合对象,这时不应该使用中介模式,而是退回一步重新思考系统的模式。

和其他模式一样,在盲目实现中介模式之前,我们需要考虑我们的特定场景。

总结

本文我们学习了中介模式。详细解释了其能解决的问题以及什么场景下使用,然后通过示例进行对比实战学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值