思考中介者模式
当多个类(对象)耦合严重时,通过中介者模式创建一个中介者,多个类不直接交互了,变成和中介者进行交互,松散耦合
1.中介者模式的本质
中介者模式的本质:封装交互。
中介者模式的本质是通过引入一个中介者对象,将系统中的一组对象之间的交互行为封装起来。它促进了对象之间的解耦,使得它们可以通过中介者对象进行间接通信,而不是直接依赖和交互。
2.何时选用中介者模式
建议在以下情况时选用中介者模式。
- 当系统中的一组对象之间存在复杂的交互行为,并且对象之间的关系呈现复杂的网状结构时,可以考虑使用中介者模式。中介者模式可以将对象之间的交互行为集中在中介者对象中,减少对象之间的直接依赖关系,降低系统的复杂性。
- 当希望通过减少对象之间的直接耦合来提高系统的灵活性和可扩展性时,可以考虑使用中介者模式。中介者模式可以减少对象之间的直接依赖,使得系统更加灵活、易于维护和扩展。
3.优缺点
中介者模式的优点。
-
松散耦合
-
减少了对象之间的直接依赖关系:中介者模式通过引入中介者对象,将对象之间的交互行为封装在中介者中,从而降低了对象之间的直接耦合度。这样一来,对象之间的依赖关系变得简单明确,易于理解和维护。
-
提高了系统的灵活性和可扩展性:由于中介者模式将对象之间的交互逻辑集中在中介者对象中,因此当系统需要新增加或修改交互行为时,只需要修改中介者对象而不影响其他对象。这样可以提高系统的灵活性和可扩展性。
-
促进了代码的重用和可维护性:中介者模式将对象之间的交互行为集中在中介者对象中,可以避免代码的重复编写和维护。通过复用中介者对象,可以减少代码量,提高代码的可维护性和可读性。
-
将控制集中管理:中介者模式将系统中的交互行为集中在中介者对象中,通过中介者对象来控制和协调对象之间的交互。这样可以更好地管理和控制系统的行为,使系统更加结构化和可控。
中介者模式的缺点。
-
中介者对象的复杂性:随着系统中对象之间的交互复杂性增加,中介者对象可能变得庞大而复杂。中介者对象需要处理多个对象之间的交互,导致中介者对象的职责和复杂性增加,可能会成为一个臃肿的类。
-
增加了系统的单点故障:中介者模式引入了中介者对象作为集中处理交互行为的角色,如果中介者对象发生故障或出现问题,整个系统的交互行为可能受到影响。
4.中介者模式的结构
- Mediator:中介者接口。在里面定义各个同事之间交互需要的方法,可以是公共的通信方法,比如 changed方法,大家都用,也可以是小范围的交互方法。
- ConcreteMediator:具体中介者实现对象。它需要了解并维护各个同事对象,并负责具体的协调各同事对象的交互关系。
- Colleague:同事类的定义,通常实现成为抽象类,主要负责约束同事对象的类型,并实现一些具体同事类之间的公共功能,比如,每个具体同事类都应该知道中介者对象,也就是具体同事类都会持有中介者对象,都可以定义到这个类里面。
- ConcreteColleague:具体的同事类,实现自己的业务,在需要与其他同事通信的时候,就与持有的中介者通信,中介者会负责与其他的同事交互。
5.实现
电脑案例
各个类互相调用,耦合严重,更改一出功能就可能影响其他地方
加上主板以后,只需要和主板沟通,集中控制
中介类:主板
同事类:Cd、Cpu、声卡
流程:
1.读取cd数据,通知主板
2.主板通知cpu处理数据
3.cpu处理完数据,通知主板
4.主板将数据交给声卡
1.同事类
/**
* @description:三个同事类都要持有中介者对象,提出一个抽象类
*/
@Getter
@AllArgsConstructor
public abstract class Colleague {
//各个类要通知中介者对象,所有要持有中介者对象
//中介者对象
private MainBoardMediator mediator;
}
/**
* @description:Cd同事类
*/
public class CdColleagues extends Colleague{
//数据
public String data="";
public String getData() {
return data;
}
public CdColleagues(MainBoardMediator mediator) {
super(mediator);
}
public void readCD(){
this.data=" 你好啊 ";
this.getMediator().read(this);
}
}
/**
* @description:Cpu同事类
*/
public class CpuColleagues extends Colleague{
//声音数据
public String soundDate="";
public String getSoundDate() {
return soundDate;
}
public CpuColleagues(MainBoardMediator mediator) {
super(mediator);
}
public void execute(String data){
soundDate = data.trim();
this.getMediator().noticeSound(this);
}
}
/**
* @description:声卡同事类
*/
public class SoundColleagues extends Colleague{
public SoundColleagues(MainBoardMediator mediator) {
super(mediator);
}
public void listen(String data){
System.out.println("-->声卡数据:"+data);
}
}
2.中介者类
/**
* @description:主板(中介者)
*/
@Setter
public class MainBoardMediator {
//中介者负责协调各个对象,所以要持有这些对象
//cpu对象
private CpuColleagues cpu=null;
//cd对象
private CdColleagues cd=null;
//声卡对象
private SoundColleagues sound=null;
/**
* 通知cpu处理数据
*/
public void read(Colleague colleague){
//cd数据
CdColleagues cdColleagues=(CdColleagues)colleague;
//主板通知cpu处理
cpu.execute(cdColleagues.getData());
}
/**
* 通知声卡播放声音
*/
public void noticeSound(Colleague colleague){
CpuColleagues cpuColleagues=(CpuColleagues)colleague;
//主板通知声卡接收数据
sound.listen(cpuColleagues.getSoundDate());
}
}
3.测试类
/**
* @description:测试类
*/
public class Client {
public static void main(String[] args) {
MainBoardMediator mediator = new MainBoardMediator();
//同事类持有中介者类
CdColleagues cdColleagues = new CdColleagues(mediator);
CpuColleagues cpuColleagues = new CpuColleagues(mediator);
SoundColleagues soundColleagues = new SoundColleagues(mediator);
//中介者类持有同事对象
mediator.setCd(cdColleagues);
mediator.setCpu(cpuColleagues);
mediator.setSound(soundColleagues);
//cd读取数据
cdColleagues.readCD();
}
}
4.结果
-->声卡数据:你好啊
购物平台的支付案例
1.中介者接口及其实现类
interface PaymentMediator {
/**
* 注册支付方法
* @param paymentMethod
*/
void registerPaymentMethod(PaymentMethod paymentMethod);
/**
* 付款
* @param amount
* @param paymentMethod
*/
void makePayment(double amount, String paymentMethod);
}
class PaymentMediatorImpl implements PaymentMediator {
private Map<String, PaymentMethod> paymentMethods;
public PaymentMediatorImpl() {
paymentMethods = new HashMap<>();
}
@Override
public void registerPaymentMethod(PaymentMethod paymentMethod) {
paymentMethods.put(paymentMethod.getName(), paymentMethod);
}
@Override
public void makePayment(double amount, String paymentMethod) {
PaymentMethod method = paymentMethods.get(paymentMethod);
if (method != null) {
method.processPayment(amount);
} else {
System.out.println("Invalid payment method.");
}
}
}
2.付款方式
/**
* 付款方式
*/
abstract class PaymentMethod {
protected PaymentMediator mediator;
protected String name;
public PaymentMethod(PaymentMediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public String getName() {
return name;
}
public abstract void processPayment(double amount);
}
/**
* 支付宝付款方式
*/
class AlipayPayment extends PaymentMethod {
public AlipayPayment(PaymentMediator mediator, String name) {
super(mediator, name);
}
@Override
public void processPayment(double amount) {
System.out.println("Processing 支付宝 payment of $" + amount);
// 实际支付逻辑
}
}
/**
* 信用卡付款方式
*/
class CreditCardPayment extends PaymentMethod {
public CreditCardPayment(PaymentMediator mediator, String name) {
super(mediator, name);
}
@Override
public void processPayment(double amount) {
System.out.println("Processing 信用卡 payment of $" + amount);
// 实际支付逻辑
}
}
3.测试类
public class Main {
public static void main(String[] args) {
PaymentMediator mediator = new PaymentMediatorImpl();
PaymentMethod creditCardPayment = new CreditCardPayment(mediator, "信用卡");
PaymentMethod alipayPayment = new AlipayPayment(mediator, "支付宝");
mediator.registerPaymentMethod(creditCardPayment);
mediator.registerPaymentMethod(alipayPayment);
double amount = 100.0;
String paymentMethod = "信用卡";
mediator.makePayment(amount, paymentMethod);
}
}
4.结果
Processing 信用卡 payment of $100.0
MyBatis中中介者模式的使用
在MyBatis中,SqlSession类作为中介者在数据库操作中发挥着关键的作用。它封装了底层的数据库连接和操作细节,并提供了一个统一的接口供开发者使用。
以下是一些关键点,说明了SqlSession如何使用中介者模式:
-
抽象接口:SqlSession类作为中介者,定义了与数据库交互的抽象接口。开发者可以通过SqlSession执行SQL语句、提交事务、获取Mapper接口实例等。
-
隐藏底层细节:SqlSession封装了底层的数据库连接和操作细节,开发者无需关心具体的数据库驱动、连接池等细节,只需要使用SqlSession提供的接口进行数据库操作。
-
协调数据库操作:SqlSession类负责协调和管理数据库操作。它会根据开发者的调用,将具体的数据库操作委托给底层的数据库连接,然后返回执行结果给开发者。
-
事务管理:SqlSession还负责事务的管理。它提供了开始事务、提交事务和回滚事务等方法,开发者可以使用这些方法来控制事务的边界和提交或回滚事务。
通过上述方式,SqlSession在MyBatis中充当了中介者的角色,将数据库操作的细节与开发者分离,提供了简单且统一的接口供开发者使用。