Skip to main content
 首页 » 编程设计

Java中介模式

2022年07月19日117虾米姐

详解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类保持不变。该示例很好说明了如何分离依赖对象使代码更易维护。

什么场景下使用中介模式

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

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

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

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

总结

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


本文参考链接:https://blog.csdn.net/neweastsun/article/details/89527445
阅读延展