中介者模式——调停者

(《设计模式解析与实战——何红辉,关爱民》读书笔记)

一、定义
中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散耦合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。中介者模式将多对多的相互作用转化为一对多的相互作用。中介者模式将对象的行为 和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。
比如,一个做App的公司大体可以分为运维、产品、开发、设计和测试,这几个部门平时肯定会有意见不合的地方,这时总经理或者老板就需要权衡利弊,使损失最小,这时总经理或者老板的角色就是充当中介者角色。

二、使用场景
当对象之间的交互操作很多且每个对象的行为操作都依赖彼此时,为防止在修改一个对象的行为时,同时涉及修改很多其他对象的行为,可采用中介者模式,来解决紧耦合问题。该模式将对象之间的多对多关系变成一对多关系,中介者对象将系统从网状结构变成以调停者为中心的星形结构,达到降低系统的复杂性,提高可扩展性的作用。

三、中介者模式的通用模式代码

/**
 * 抽象中介者:定义了同事对象到中介者对象的接口,一般以抽象类的方法实现
 */
public abstract class Mediator {
    // 具体同事类A
    protected ConcreteColleagueA conlleagueA;
    // 具体同事类B
    protected ConcreteColleagueB conlleagueB;

    // 抽象中介方法、子类实现
    public abstract void method();

    public void setConlleagueA(ConcreteColleagueA conlleagueA) {
        this.conlleagueA = conlleagueA;
    }

    public void setConlleagueB(ConcreteColleagueB conlleagueB) {
        this.conlleagueB = conlleagueB;
    }
}
package com.mediator.model;

/**
 * 具体中介者:实现父类定义的方法,它从具体的的同事对象接收消息,向具体同事对象发出命令
 */
public class ConcreteMediator extends Mediator{

    @Override
    public void method() {
        conlleagueA.action();
        conlleagueB.action();
    }
}
package com.mediator.model;

/**
 * 抽象同事:定义了中介者对象的接口,它只知道中介者而不知道其他的同事对象
 */
public abstract class Colleague {
    // 中介者对象
    protected Mediator mediator;

    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }

    /**
     * 同事角色的具体行为,由子类去实现
     */
    public abstract void action();

}
package com.mediator.model;

/**
 * 具体同事A:每个具体同事类都知道本身在小范围内的行为,而不知道他在大范围内的目的
 */
public class ConcreteColleagueA extends Colleague {

    public ConcreteColleagueA(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void action() {
        System.out.println("ColleagueA 将信息递交给中介者处理");
    }
}
package com.mediator.model;

/**
 * 具体同事B:每个具体同事类都知道本身在小范围内的行为,而不知道他在大范围内的目的
 */
public class ConcreteColleagueB extends Colleague {

    public ConcreteColleagueB(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void action() {
        System.out.println("ColleagueB 将信息递交给中介者处理");
    }
}

四、中介者模式在Android中的应用
比如,一个登陆界面通常包含两个文本框、两个按钮、两个复选框。
业务需求:
(1)用户名没有输入时除了取消按钮外均不可用;
(2)密码没有输入,除了文本框,记住账户复选框和取消按钮外其余均不可用,当且仅当账户密码均正确时所有空间才可用;
(3)如果勾选了自动登录,记住账户也会自动勾选,并且账户密码不可编辑;
(4)自动登录取消,勾选记住账户,会置空密码框。
当然平常我们不会去套用中介者模式框架,大多数情况下我们直接让Activity来充当一个中介者并在其中处理相关的逻辑。

布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/ll_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:orientation="vertical">

        <EditText
            android:id="@+id/et_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:hint="账户" />

        <EditText
            android:id="@+id/et_password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:hint="密码"
            android:password="true" />
    </LinearLayout>

    <RelativeLayout
        android:id="@+id/rl_layout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ll_layout"
        android:layout_marginTop="20dp"
        android:orientation="horizontal">

        <CheckBox
            android:id="@+id/cb_remeber"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:text="记住账户" />

        <CheckBox
            android:id="@+id/cb_auto"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="5dp"
            android:text="自动登录" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/rl_layout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/rl_layout1"
        android:layout_marginTop="20dp">

        <Button
            android:id="@+id/btn_ok"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:text="确定" />

        <Button
            android:id="@+id/btn_cancle"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="5dp"
            android:text="取消" />
    </RelativeLayout>
</RelativeLayout>

这里写图片描述

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Toast;

public class LoginActivity extends AppCompatActivity {

    private EditText mEtAccount, mEtPassword;
    private Button mBtnOK, mBtnCancle;
    private CheckBox mCbRemember, mCbAuto;

    // 账户文本,密码文本
    private String mStrAccount, mStrPassword;
    // 是否记住账户,是否自动登录
    private boolean isRemember, isAuto;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        // 初始化View
        initViews();
        // 监听账户文本改变
        textAccountWatch();
        // 监听密码文本改变
        textPasswordWatch();
        // 监听确定按钮事件
        btnOKListener();
        // 监听取消按钮事件
        btnCancleListener();
        // 监听自动登录复选框
        cbAutoListener();
        // 监听记住账户复选框
        cbRememberListener();

    }

    private void cbRememberListener() {
        mCbRemember.setEnabled(false);
        mCbRemember.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // 回传数据
                isRemember = isChecked;
                // 通知Activity状态改变
                change();
            }
        });
    }

    private void cbAutoListener() {
        mCbAuto.setEnabled(false);
        mCbAuto.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // 回传数据
                isAuto = isChecked;
                // 通知Activity状态改变
                change();
            }
        });
    }

    private void btnCancleListener() {
        mBtnCancle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(LoginActivity.this, "Login cancle!", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void btnOKListener() {
        mBtnOK.setEnabled(false);
        mBtnOK.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(LoginActivity.this, "Login success!", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void textPasswordWatch() {
        mEtPassword.setEnabled(false);
        mEtPassword.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // 回传数据
                mStrPassword = s.toString();
                // 通知Activity状态改变
                change();
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
    }

    private void textAccountWatch() {
        mEtAccount.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // 回传数据
                mStrAccount = s.toString();
                // 通知Activity状态改变
                change();
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
    }

    private void initViews() {
        mEtAccount = (EditText) findViewById(R.id.et_account);
        mEtPassword = (EditText) findViewById(R.id.et_password);
        mBtnOK = (Button) findViewById(R.id.btn_ok);
        mBtnCancle = (Button) findViewById(R.id.btn_cancle);
        mCbRemember = (CheckBox) findViewById(R.id.cb_remember);
        mCbAuto = (CheckBox) findViewById(R.id.cb_auto);
    }

    /**
     * 各控件状态改变后协调各控件状态显示
     */
    private void change() {
        // 账户为空
        if (TextUtils.isEmpty(mStrAccount)) {
            mEtPassword.setEnabled(false);

            mCbRemember.setEnabled(false);
            mCbAuto.setEnabled(false);

            mBtnOK.setEnabled(false);
            mBtnCancle.setEnabled(true);
            // 账户不空,密码为空
        } else if (!TextUtils.isEmpty(mStrAccount) && TextUtils.isEmpty(mStrPassword)) {
            mEtPassword.setEnabled(true);

            mCbAuto.setEnabled(false);
            mCbRemember.setEnabled(true);

            mBtnOK.setEnabled(false);
            mBtnCancle.setEnabled(true);
            // 账户不空,密码不空
        } else if (!TextUtils.isEmpty(mStrAccount) && !TextUtils.isEmpty(mStrPassword)) {
            mEtPassword.setEnabled(true);

            mCbRemember.setEnabled(true);
            mCbAuto.setEnabled(true);

            mBtnOK.setEnabled(true);
            mBtnCancle.setEnabled(true);
        }
    }
}

Activity目录结构:
这里写图片描述

这里写图片描述

五、总结
在面向对象的编程语言里,一个类必然会与其他类产生依赖关系,如果这种依赖关系如网状般错综复杂,那么必然会影响我们的代码逻辑以及执行效率,适当的使用中介者模式可以对这种依赖关系进行解耦使逻辑结构清晰;
但是,如果及各类间的依赖关系并不复杂,使用中介者模式反而会使得原本不复杂的逻辑结构变得复杂。
所以,我们在决定使用中介者模式之前要多方考虑、权衡利弊。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值