《C++新经典设计模式》之第17章 中介者模式
2023-12-14 12:59:20
《C++新经典设计模式》之第17章 中介者模式
中介者模式.cpp
#include <iostream>
#include <map>
#include <memory>
using namespace std;
// 中介者封装一系列的对象交互
// 4种角色
// Mediator(抽象中介者类),定义接口,各个同事类通过该接口与中介者通信
// ConcreteMediator(具体中介者类),实现接口,保存同事类指针用于与同事对象通信实现协作行为
// Colleague(抽象同事类),定义同事共有方法和抽象方法,同时维持中介者对象指针用于通信
// ConcreteColleague(具体同事类),实现方法
// 可结合观察者模式,即中介者实现为观察者,各个同事类实现为观察目标
namespace ns1
{
class CtlParent // UI控件类
{
protected:
string m_caption; // 控件上面显示的文字内容,本范例假设每个UI控件上的文字都不同
public:
virtual ~CtlParent() {}
CtlParent(const string &caption) : m_caption(caption) {}
public: // 当UI控件发生变化时该成员函数会被调用
virtual void Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist) = 0; // 形参所代表的map容器中包含着所有对话框中涉及到的UI控件
virtual void Enable(bool sign) const = 0; // 设置UI控件启用或禁用
};
class Button : public CtlParent // 普通按钮相关类
{
public:
Button(const string &caption) : CtlParent(caption) {}
public:
void Enable(bool sign) const override // 设置按钮的启用或禁用
{
if (sign)
cout << "button \"" << m_caption << "\" enable" << endl;
else
cout << "button \"" << m_caption << "\" disable" << endl;
}
// 按钮被按下时该成员函数会被调用
void Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist) override;
};
class RadioBtn : public CtlParent // 单选按钮相关类
{
public:
RadioBtn(const string &caption) : CtlParent(caption) {}
public:
void Enable(bool sign) const override {} // 设置单选按钮的启用或禁用
// 设置单选按钮为被选中或者被取消选中,被选中的单选按钮中间有个黑色实心圆点
void Selected(bool sign) const
{
if (sign)
cout << "radio button \"" << m_caption << "\" selected" << endl;
else
cout << "radio button \"" << m_caption << "\" not selected" << endl;
}
// 单选按钮被单击时该成员函数会被调用
void Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist) override;
};
class EditCtl : public CtlParent // 编辑框相关类
{
string m_content = ""; // 编辑框中的内容
public:
EditCtl(const string &caption) : CtlParent(caption) {}
public:
void Enable(bool sign) const override // 设置编辑框的启用或禁用
{
if (sign)
cout << "edit box \"" << m_caption << "\" enable" << endl;
else
cout << "edit box \"" << m_caption << "\" disable" << endl;
}
// 是否编辑框中的内容为空
bool isContentEmpty() const { return m_content.empty(); }
// 编辑框内容发生变化时该成员函数会被调用
void Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist) override;
};
// 按钮被按下时该成员函数会被调用
void Button::Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist)
{
if (m_caption == "sign in") // 按下的是登录按钮
cout << "Start the game login verification, and decide whether to enter the game or give a prompt according to the verification result!" << endl;
else if (m_caption == "exit") // 按下的是退出按钮,则退出整个游戏
cout << "Game exit, goodbye!" << endl;
}
// 单选按钮被单击时该成员函数会被调用
void RadioBtn::Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist)
{
if (m_caption == "visitor login")
{
static_pointer_cast<RadioBtn>(tmpuictllist["visitor login"])->Selected(true); // “游客登录”单选按钮设置为选中
static_pointer_cast<RadioBtn>(tmpuictllist["account login"])->Selected(false); // “账号登录”单选按钮设置为取消选中
tmpuictllist["account"]->Enable(false); // “账号”编辑框设置为禁用
tmpuictllist["password"]->Enable(false); // “密码”编辑框设置为禁用
tmpuictllist["sign in"]->Enable(true); // “登录”按钮设置为启用
}
else if (m_caption == "account login")
{
static_pointer_cast<RadioBtn>(tmpuictllist["visitor login"])->Selected(false); // “游客登录”单选按钮设置为取消选中
static_pointer_cast<RadioBtn>(tmpuictllist["account login"])->Selected(true); // “账号登录”单选按钮设置为选中
tmpuictllist["account"]->Enable(true); // “账号”编辑框设置为启用
tmpuictllist["password"]->Enable(true); // “密码”编辑框设置为启用
// 如果“账号”编辑框或者“密码”编辑框有一个为空,则不允许登录
if (static_pointer_cast<EditCtl>(tmpuictllist["account"])->isContentEmpty() || static_pointer_cast<EditCtl>(tmpuictllist["password"])->isContentEmpty())
tmpuictllist["sign in"]->Enable(false); // “登录”按钮设置为禁用
else
tmpuictllist["sign in"]->Enable(true); // “登录”按钮设置为启用
}
}
// 编辑框内容发生变化时该成员函数会被调用
void EditCtl::Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist)
{
// 如果“账号”编辑框或者“密码”编辑框有一个为空,则不允许登录
if (static_pointer_cast<EditCtl>(tmpuictllist["account"])->isContentEmpty() || static_pointer_cast<EditCtl>(tmpuictllist["password"])->isContentEmpty())
tmpuictllist["sign in"]->Enable(false); // “登录”按钮设置为禁用
else
tmpuictllist["sign in"]->Enable(true); // “登录”按钮设置为启用
}
}
namespace ns2
{
class CtlParent; // 类前向声明
class Mediator // 中介者父类
{
public:
virtual ~Mediator() {}
public:
virtual void createCtrl() = 0; // 创建所有需要用到的UI控件
virtual void ctlChanged(CtlParent *const) = 0; // 当某个UI控件发生变化时调用中介者对象的该成员函数来通知中介者
};
class CtlParent // UI控件类的父类
{
protected:
Mediator *m_pmediator; // 指向中介者对象的指针
string m_caption; // 控件上面显示的文字内容,可能并不是所有控件都需要但这里为显示方便依旧引入
public:
virtual ~CtlParent() {}
CtlParent(Mediator *const ptmpm, const string &caption) : m_pmediator(ptmpm), m_caption(caption) {}
public: // 当UI控件发生变化时该成员函数会被调用
virtual void Changed() { m_pmediator->ctlChanged(this); } // 通知中介者对象,所有事情让中介者对象去做
virtual void Enable(bool sign) = 0; // 设置UI控件启用或禁用
};
class Button : public CtlParent // 普通按钮相关类
{
public:
Button(Mediator *const ptmpm, const string &caption) : CtlParent(ptmpm, caption) {}
void Enable(bool sign) override // 设置按钮的启用或禁用
{
if (sign == true)
cout << "button \"" << m_caption << "\" enable" << endl;
else
cout << "button \"" << m_caption << "\" disable" << endl;
}
};
class RadioBtn : public CtlParent // 单选按钮相关类
{
public:
RadioBtn(Mediator *const ptmpm, const string &caption) : CtlParent(ptmpm, caption) {}
void Enable(bool sign) override {} // 设置单选按钮的启用或禁用
void Selected(bool sign) // 设置单选按钮为被选中或者被取消选中,被选中的单选按钮中间有个黑色实心圆点
{
if (sign == true)
cout << "radio button \"" << m_caption << "\" selected" << endl;
else
cout << "radio button \"" << m_caption << "\" not selected" << endl;
}
};
class EditCtl : public CtlParent // 编辑框相关类
{
string m_content = ""; // 编辑框中的内容
public:
EditCtl(Mediator *const ptmpm, const string &caption) : CtlParent(ptmpm, caption) {}
void Enable(bool sign) override // 设置编辑框的启用或禁用
{
if (sign == true)
cout << "edit box \"" << m_caption << "\" enable" << endl;
else
cout << "edit box \"" << m_caption << "\" disable" << endl;
}
bool isContentEmpty() const { return m_content.empty(); } // 是否编辑框中的内容为空
};
class concrMediator : public Mediator // 具体中介者类
{
public: // 为方便外界使用,这里以public修饰,实际项目中可以写一个成员函数来return这些指针
shared_ptr<Button> mp_login; // 登录按钮
shared_ptr<Button> mp_logout; // 退出按钮
shared_ptr<RadioBtn> mp_rbtn1; // 游客登录单选按钮
shared_ptr<RadioBtn> mp_rbtn2; // 账号登录单选按钮
shared_ptr<EditCtl> mp_edtctl1; // 账号编辑框
shared_ptr<EditCtl> mp_edtctl2; // 密码编辑框
public:
void createCtrl() override // 创建各种UI控件
{
// 当然,各种UI控件对象在外面创建,然后把地址传递进来也可以
mp_login = make_shared<Button>(this, "sign in");
mp_logout = make_shared<Button>(this, "exit");
mp_rbtn1 = make_shared<RadioBtn>(this, "visitor login");
mp_rbtn2 = make_shared<RadioBtn>(this, "account login");
mp_edtctl1 = make_shared<EditCtl>(this, "account editing box");
mp_edtctl2 = make_shared<EditCtl>(this, "password editing box");
// 设置一下缺省的UI控件状态
mp_rbtn1->Selected(true); // “游客登录”单选按钮设置为选中
mp_rbtn2->Selected(false); // “账号登录”单选按钮设置为取消选中
mp_edtctl1->Enable(false); // “账号”编辑框设置为禁用
mp_edtctl2->Enable(false); // “密码”编辑框设置为禁用
mp_login->Enable(true); // “登录”按钮设置为启用
mp_logout->Enable(true); // “退出”按钮设置为启用
}
// 当某个UI控件发生变化时调用中介者对象的该成员函数来通知中介者
virtual void ctlChanged(CtlParent *const p_ctrl)
{
if (p_ctrl == mp_login.get()) // 登录按钮被单击
cout << "Start the game login verification, and decide whether to enter the game or give a prompt according to the verification result!" << endl;
else if (p_ctrl == mp_logout.get()) // 退出按钮被单击
cout << "Game exit, goodbye!" << endl; // 退出整个游戏
if (p_ctrl == mp_rbtn1.get()) // 游客登录单选按钮被单击
{
mp_rbtn1->Selected(true); // “游客登录”单选按钮设置为选中
mp_rbtn2->Selected(false); // “账号登录”单选按钮设置为取消选中
mp_edtctl1->Enable(false); // “账号”编辑框设置为禁用
mp_edtctl2->Enable(false); // “密码”编辑框设置为禁用
mp_login->Enable(true); // “登录”按钮设置为启用
}
else if (p_ctrl == mp_rbtn2.get()) // 账号登录单选按钮被单击
{
mp_rbtn1->Selected(false); // “游客登录”单选按钮设置为取消选中
mp_rbtn2->Selected(true); // “账号登录”单选按钮设置为选中
mp_edtctl1->Enable(true); // “账号”编辑框设置为启用
mp_edtctl2->Enable(true); // “密码”编辑框设置为启用
if (mp_edtctl1->isContentEmpty() || mp_edtctl2->isContentEmpty()) // 如果“账号”编辑框或者“密码”编辑框有一个为空,则不允许登录
mp_login->Enable(false); // “登录”按钮设置为禁用
else
mp_login->Enable(true); // “登录”按钮设置为启用
}
if (p_ctrl == mp_edtctl1.get() || p_ctrl == mp_edtctl2.get()) // 账号或密码编辑框内容发生改变
if (mp_edtctl1->isContentEmpty() || mp_edtctl2->isContentEmpty()) // 如果“账号”编辑框或者“密码”编辑框有一个为空,则不允许登录
mp_login->Enable(false); // “登录”按钮设置为禁用
else
mp_login->Enable(true); // “登录”按钮设置为启用
}
};
}
int main()
{
#if 0
using namespace ns1;
// 创建各种UI控件
map<string, shared_ptr<CtlParent>> uictllist; // 将所有创建的UI控件保存到map容器中,方便进行参数传递
uictllist["sign in"] = make_shared<Button>("sign in");
uictllist["exit"] = make_shared<Button>("exit");
uictllist["visitor login"] = make_shared<RadioBtn>("visitor login");
uictllist["account login"] = make_shared<RadioBtn>("account login");
uictllist["account"] = make_shared<EditCtl>("account");
uictllist["password"] = make_shared<EditCtl>("password");
// 设置一下缺省的UI控件状态
// 因为只有子类型才有Selected成员函数,所以这里需要用到强制类型转换
static_pointer_cast<RadioBtn>(uictllist["visitor login"])->Selected(true); // “游客登录”单选按钮设置为选中
static_pointer_cast<RadioBtn>(uictllist["account login"])->Selected(false); // “账号登录”单选按钮设置为取消选中
uictllist["account"]->Enable(false); // “账号”编辑框设置为禁用
uictllist["password"]->Enable(false); // “密码”编辑框设置为禁用
uictllist["sign in"]->Enable(true); // “登录”按钮设置为启用
uictllist["exit"]->Enable(true); // “退出”按钮设置为启用
cout << "--------------------------" << endl;
uictllist["account login"]->Changed(uictllist); // 模拟“账号登录”单选按钮被单击选中
#endif
#if 1
using namespace ns2;
concrMediator mymedia;
mymedia.createCtrl();
cout << "-------------when \"account login\" radio button pressed:-------------" << endl;
// 模拟“账号”按钮被按下,则去通知中介者,由中介者实现具体的逻辑处理
mymedia.mp_rbtn2->Changed();
#endif
cout << "Over!\n";
return 0;
}
文章来源:https://blog.csdn.net/oqqyx1234567/article/details/128665797
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!