C++设计模式整理011-备忘录模式和中介者模式

目录

16. 备忘录模式

16.1 实例2

17. 中介者模式

17.1 实例2


16. 备忘录模式

        备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原来保存的状态。

        备忘录模式中需要定义的角色类:

                1. Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。

                2. Memento(备忘录):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。

                3. Caretaker(管理者):负责备忘录Memento,不能对Memento的内容进行访问或者操作。

/*
 * 关键代码:Memento类、Originator类、Caretaker类;Originator类不与Memento类耦合,而是与Caretaker类耦合。
*/

#include <iostream>

using namespace std;

//需要保存的信息
typedef struct  
{
    int grade;
    string arm;
    string corps;
}GameValue;

//Memento类
class Memento   
{
public:
    Memento(){}
    Memento(GameValue value):m_gameValue(value){}
    GameValue getValue()
    {
        return m_gameValue;
    }
private:
    GameValue m_gameValue;
};

//Originator类
class Game   
{
public:
    Game(GameValue value):m_gameValue(value)
    {}
    void addGrade()  //等级增加
    {
        m_gameValue.grade++;
    }
    void replaceArm(string arm)  //更换武器
    {
        m_gameValue.arm = arm;
    }
    void replaceCorps(string corps)  //更换工会
    {
        m_gameValue.corps = corps;
    }
    Memento saveValue()    //保存当前信息
    {
        Memento memento(m_gameValue);
        return memento;
    }
    void load(Memento memento) //载入信息
    {
        m_gameValue = memento.getValue();
    }
    void showValue()
    {
        cout << "Grade: " << m_gameValue.grade << endl;
        cout << "Arm  : " << m_gameValue.arm.data() << endl;
        cout << "Corps: " << m_gameValue.corps.data() << endl;
    }
private:
    GameValue m_gameValue;
};

//Caretaker类
class Caretake 
{
public:
    void save(Memento memento)  //保存信息
    {
        m_memento = memento;
    }
    Memento load()            //读已保存的信息
    {
        return m_memento;
    }
private:
    Memento m_memento;
};

int main()
{
    GameValue v1 = {0, "Ak", "3K"};
    Game game(v1);    //初始值
    game.addGrade();
    game.showValue();
    cout << "----------" << endl;
    Caretake care;
    care.save(game.saveValue());  //保存当前值
    game.addGrade();          //修改当前值
    game.replaceArm("M16");
    game.replaceCorps("123");
    game.showValue();
    cout << "----------" << endl;
    game.load(care.load());   //恢复初始值
    game.showValue();
    return 0;
}

16.1 实例2

        在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态[DP]。

        举个简单的例子,我们玩游戏时都会保存进度,所保存的进度以文件的形式存在。这样下次就可以继续玩,而不用从头开始。这里的进度其实就是游戏的内部状态,而这里的文件相当于是在游戏之外保存状态。这样,下次就可以从文件中读入保存的进度,从而恢复到原来的状态。这就是备忘录模式。

        给出备忘录模式的UML图,以保存游戏的进度为例。

 

        Memento类定义了内部的状态,而Caretake类是一个保存进度的管理者,GameRole类是游戏角色类。可以看到GameRole的对象依赖于Memento对象,而与Caretake对象无关。下面给出一个简单的是实现。

//需保存的信息
class Memento  
{
public:
	int m_vitality; //生命值
	int m_attack;   //进攻值
	int m_defense;  //防守值
public:
	Memento(int vitality, int attack, int defense): 
	  m_vitality(vitality),m_attack(attack),m_defense(defense){}
	Memento& operator=(const Memento &memento) 
	{
		m_vitality = memento.m_vitality;
		m_attack = memento.m_attack;
		m_defense = memento.m_defense;
		return *this;
	}
};

//游戏角色
class GameRole  
{
private:
	int m_vitality;
	int m_attack;
	int m_defense;
public:
	GameRole(): m_vitality(100),m_attack(100),m_defense(100) {}
	Memento Save()  //保存进度,只与Memento对象交互,并不牵涉到Caretake
	{ 
		Memento memento(m_vitality, m_attack, m_defense);
		return memento;
	}
	void Load(Memento memento)  //载入进度,只与Memento对象交互,并不牵涉到Caretake
	{
		m_vitality = memento.m_vitality;
		m_attack = memento.m_attack; 
		m_defense = memento.m_defense;
	}
	void Show() { cout<<"vitality : "<< m_vitality<<", attack : "<< m_attack<<", defense : "<< m_defense<<endl; }
	void Attack() { m_vitality -= 10; m_attack -= 10;  m_defense -= 10; }
};

//保存的进度库
class Caretake  
{
public:
	Caretake() {}
	void Save(Memento menento) { m_vecMemento.push_back(menento); }
	Memento Load(int state) { return m_vecMemento[state]; }
private:
	vector<Memento> m_vecMemento;
};

// 客户使用方式:

//测试案例
int main()
{	
	Caretake caretake;
	GameRole role; 
	role.Show();   //初始值
	caretake.Save(role.Save()); //保存状态
	role.Attack();   
	role.Show();  //进攻后
	role.Load(caretake.Load(0)); //载入状态 
	role.Show();  //恢复到状态0
	return 0;
}

参考资料:https://blog.csdn.net/wuzhekai1985/article/details/6672906

参考资料:https://www.cnblogs.com/chengjundu/p/8473564.html

 

17. 中介者模式

        中介者模式:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之前的交互。

        如果对象与对象之前存在大量的关联关系,若一个对象改变,常常需要跟踪与之关联的对象,并做出相应的处理,这样势必会造成系统变得复杂,遇到这种情形可以考虑使用中介者模式。当多个对象存在关联关系时,为它们设计一个中介对象,当一个对象改变时,只需要通知它的中介对象,再由它的中介对象通知每个与它相关的对象。

/*
* 关键代码:将相关对象的通信封装到一个类中单独处理。
*/
#include <iostream>

using namespace std;

class Mediator;

//抽象同事类。
class Businessman
{
public:
    Businessman(){}
    Businessman(Mediator* mediator) : m_pMediator(mediator){}

    virtual ~Businessman(){}

    virtual void setMediator(Mediator* m)
    {
        m_pMediator = m;
    }

    virtual void sendMessage(const string& msg) = 0;
    virtual void getMessage(const string& msg) = 0;

protected:
    Mediator* m_pMediator;
};

//抽象中介者类。
class  Mediator
{
public:
    virtual ~Mediator(){}
    virtual void setBuyer(Businessman* buyer) = 0;
    virtual void setSeller(Businessman* seller) = 0;
    virtual void send(const string& msg, Businessman* man) = 0;
};

//具体同事类
class Buyer : public Businessman
{
public:
    Buyer() : Businessman(){}
    Buyer(Mediator* mediator) : Businessman(mediator){}

    void sendMessage(const string& msg) override
    {
        m_pMediator->send(msg, this);
    }

    void getMessage(const string& msg)
    {
        cout << "Buyer recv: " << msg.data() << endl;
    }
};

//具体同事类
class Seller : public Businessman
{
public:
    Seller() : Businessman(){}
    Seller(Mediator* mediator) : Businessman(mediator){}

    void sendMessage(const string& msg) override
    {
        m_pMediator->send(msg, this);
    }

    void getMessage(const string& msg)
    {
        cout << "Seller recv: " << msg.data() << endl;
    }
};

//具体中介者类
class HouseMediator : public Mediator
{
public:
    void setBuyer(Businessman* buyer) override
    {
        m_pBuyer = buyer;
    }

    void setSeller(Businessman* seller) override
    {
        m_pSeller = seller;
    }

    void send(const string& msg, Businessman* man) override
    {
        if(man == m_pBuyer)
        {
            m_pSeller->getMessage(msg);
        }
        else if(man == m_pSeller)
        {
            m_pBuyer->getMessage(msg);
        }
    }

private:
    Businessman* m_pBuyer;
    Businessman* m_pSeller;
};

int main()
{
    HouseMediator* hMediator = new HouseMediator;
    Buyer* buyer = new Buyer(hMediator);
    Seller* seller = new Seller(hMediator);

    hMediator->setBuyer(buyer);
    hMediator->setSeller(seller);

    buyer->sendMessage("Sell not to sell?");
    seller->sendMessage("Of course selling!");

    delete buyer;
    buyer = nullptr;

    delete seller;
    seller = nullptr;
    delete hMediator;
    hMediator = nullptr;


    return 0;
}

17.1 实例2

        用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

        本文就以租房为例子,如果没有房屋中介,那么房客要自己找房东,而房东也要自己找房客,非常不方便。有了房屋中介机构就方便了,房东可以把要出租的房屋信息放到中介机构,而房客可以去中介机构咨询。

        在软件中,就是多个对象之间需要通信,如果没有中介,对象就需要知道其他对象,最坏情况下,可能需要知道所有其他对象,而有了中介对象就方便多了,对象只需与中介对象通信,而不用知道其他的对象。这就是中介者模式,下面以租房为例,给出中介者模式的UML图。

 

        实现不难,下面给出C++的实现:

class Mediator;

//抽象人
class Person
{
protected:
	Mediator *m_mediator; //中介
public:
	virtual void SetMediator(Mediator *mediator){} //设置中介
	virtual void SendMessage(string message) {}    //向中介发送信息
	virtual void GetMessage(string message) {}     //从中介获取信息
};

//抽象中介机构
class Mediator
{
public:
	virtual void Send(string message, Person *person) {}
	virtual void SetA(Person *A) {}  //设置其中一方
	virtual void SetB(Person *B) {}
};

//租房者
class Renter: public Person
{
public:
	void SetMediator(Mediator *mediator) { m_mediator = mediator; }
	void SendMessage(string message) { m_mediator->Send(message, this); }
	void GetMessage(string message) { cout<<"租房者收到信息"<<message; }
};

//房东
class Landlord: public Person
{
public:
	void SetMediator(Mediator *mediator) { m_mediator = mediator; }
	void SendMessage(string message) { m_mediator->Send(message, this); }
	void GetMessage(string message) { cout<<"房东收到信息:"<<message; }
};

//房屋中介
class HouseMediator : public Mediator
{
private:
	Person *m_A; //租房者
	Person *m_B; //房东
public:
	HouseMediator(): m_A(0), m_B(0) {}
	void SetA(Person *A) { m_A = A; }
	void SetB(Person *B) { m_B = B; }
	void Send(string message, Person *person) 
	{
		if(person == m_A) //租房者给房东发信息
			m_B->GetMessage(message); //房东收到信息
		else
			m_A->GetMessage(message);
	}
};

// 客户使用方式如下:

//测试案例
int main()
{	
	Mediator *mediator = new HouseMediator();
	Person *person1 = new Renter();    //租房者
	Person *person2 = new Landlord();  //房东
	mediator->SetA(person1);
	mediator->SetB(person2);
	person1->SetMediator(mediator);
	person2->SetMediator(mediator);
	person1->SendMessage("我想在XXX路附近租套房子,价格800元一个月\n");
	person2->SendMessage("出租房子:XXXXXX,70平米,1000元一个月\n");
	delete person1; delete person2; delete mediator;
	return 0;
}

 

参考资料:https://blog.csdn.net/wuzhekai1985/article/details/6673603

参考资料:https://www.cnblogs.com/chengjundu/p/8473564.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公众号:程序喵星人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值