观察者模式

/*
 观察者模式:观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,
           使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
 
举个例子:
 一家人捉迷藏,小朋友数数从1到100之后,开始找爸爸妈妈。此时的需求是爸爸妈妈随时知道小朋友数到了多少,以便选择躲藏的地方。
 
简单做法如下:
class person
{
    void action(int status)
    {
        cur_status = status;
        if (cur_status < 50)
        {
            cout << "慢悠悠寻找位置" << endl;
        }
        else
        {
            cout << "抓紧时间" << endl;
        }
    }
private:
    int cur_status;
};
 
class child
{
public:
    count()
    {
        for (int i = 1; i <= 100; i++)
        {
            status = i;
            for (auto it = persons.begin(); it != persons.end(); it++)
            {
                it->action(status);
            }
        }
    }
private:
    vector<person> persons;
    int status;
    ...
};
 
 缺点:
 这种写法,看起来OK功能完成了,但是类的设计不符合伦理,child类中怎么能有person呢?
 同时如果还有一只聪明的小狗也会玩住迷藏怎么办呢?在child类里面加一个vector<dog>属性吗?
 万一还有猴子呢,child岂不是要无限扩大?
 
 此时就想拿能不能直接放一个vector<animal*>属性,然后人、狗、猴子都继承animal呢?
 可以是可以,但是animal没有action(status)方法啊!
 于是又想,animal里面就是弄一个纯虚函数,人、狗、猴子去实现这个函数。
 
class animal
{
public:
 virtual void action(status) = 0;
}
 
class person : public animal
{
public:
    void action(int status)
    {
         cur_status = status;
         if (cur_status < 50)
         {
         cout << "慢悠悠寻找位置" << endl;
         }
         else
         {
         cout << "抓紧时间" << endl;
         }
    }
private:
    int cur_status;
};
 
class child
{
 public:
     void addObserver(animals *ser)
     {
        observers.push_back(ser);
     }
     void count()
     {
         for (int i = 1; i <= 100; i++)
         {
            status = i;
            for (auto it = observers.begin(); it != observers.end(); it++)
            {
                (*it)->action(status);
            }
         }
     }
 private:
    vector<animal*> observers;
    int status;
    ...
}

 
这样就可以将animal视为一个观察者类,observer类。但他只是一个抽象类,不具备actionn功能,
具体的观察者类应该是人,猫、狗,他们会根据当前小孩子的数数状态,做出不同行为。

最后为了更加符合逻辑,小朋友的属性应该是name,age之类的信息,而不是状态,观察者们。所以最好设计
 一个Observed类,里面有vector<animal*> observers,int status;这两个属性。同时具有添加,删除观察者等方法,和一个updateStatus的纯虚函数

 */

#include <iostream>
#include <vector>
#include <string>

using namespace std;

class Observe
{
public:
    Observe()
    {
    }
    virtual ~Observe()
    {
    }
    virtual void action(int status) = 0;
};

class Observed
{
public:
    void addObserver(Observe *obs)
    {
        observers.push_back(obs);
    }
    
    void deleteOberver(Observe *obs)
    {
        for (auto it = observers.begin(); it != observers.end(); it++)
        {
            if ((*it) == obs)
            {
                observers.erase(it);
            }
        }
    }
    void noticeObserve()
    {
        for (auto it = observers.begin(); it != observers.end(); it++)
        {
            (*it)->action(status);
        }

    }
    virtual void updateStatus() = 0;
    
protected:
    vector<Observe*> observers;
    int status;
};

class Child: public Observed
{
public:
    void updateStatus()
    {
        for (int i = 1; i <= 100; i++)
        {
            status++;
            noticeObserve();
        }
    }
private:
    int age;
    string name;
};

class Parents : public Observe
{
public:
    void action(int status)
    {
        cout << "数到" << status << "时父母的思维:";
        if (status < 50)
        {
            cout << "慢慢来" << endl;
        }
        else
        {
            cout << "抓紧时间" << endl;
        }
    }
};

class Dog : public Observe
{
public:
    void action(int status)
    {
        cout << "数到" << status << "时小狗的思维:";
        if (status < 50)
        {
            cout << "汪汪汪,跟着人跑" << endl;
        }
        else
        {
            cout << "完了完了,躲在哪?我要捣乱" << endl;
        }
    }
};


int main()
{
    Child ch;
    Parents *p = new Parents;
    Dog *d = new Dog;
    ch.addObserver(p);
    ch.addObserver(d);
    ch.updateStatus();
    delete p;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值