面向对象程序设计第六次实验课——群与子群(装饰模式)

装饰模式简介(内容来自head first 设计模式):
http://blog.csdn.net/a19881029/article/details/8980503

group.h

#pragma once
#include <vector>
#include <string>
#include "Person.h"
using namespace std;

// Group 是整个装饰模式中的concrete component, 由于只有一个concrete component,
// 所以实际上Group也充当了component的职责 
class Person;
class Group {
    public:
        Group(void) = default;
        Group(const vector<Person *> &person);
        Group(const Group& grp) = default;
        virtual Group& operator= (const Group& grp);
        virtual ~Group(void) = default;

        virtual void onReceiveMessage(const string &msg, const Person &per);
        virtual bool onAddPerson(const Person& per);
        virtual bool onDelPerson(const Person& per);    

        virtual void showRecord(void);
        virtual bool checkPerson(const Person &per) const;
        virtual const vector<string>& getRecord(void) const;
    private:
        vector<Person *> m_person;
        vector<string> m_record;
        void action(void);
//      vector<Group *> m_subGroup;
};

inline const vector<string>& Group::getRecord(void) const
{
    return m_record;
}

group.cpp

#include "Group.h"
#include <iostream>
using namespace std;

Group::Group(const vector<Person *> &person) 
    : m_person(person)
{}

Group& Group::operator=(const Group &grp)
{
    if (this != &grp) {
        m_person = grp.m_person;
        m_record = grp.m_record;
    }
    return (*this);
}

void Group::onReceiveMessage(const string &msg, const Person &per)
{
    if (checkPerson(per)) {
        m_record.push_back(per.getName() + "说:" + msg);
        cout << per.getName() + "说:" + msg << endl;
    }
    return ;
}

void Group::action(void) {}

void Group::showRecord(void)
{
    for (int i = 0; i < m_record.size(); i ++) {
        cout << m_record[i] << endl;
    }
    return ;
}

bool Group::onAddPerson(const Person& per)
{
    if (!checkPerson(per)) {
        m_person.push_back(const_cast<Person *>(&per));
    }
}
bool Group::onDelPerson(const Person& per)
{
    for (auto it = m_person.begin(); it != m_person.end(); it ++) {
        if (*it == &per) {
            m_person.erase(it);
            return true;
        }
    }
    return false;
}

bool Group::checkPerson(const Person &per) const
{
    for (int i = 0; i < m_person.size(); i ++) {
        if (m_person[i] == &per) {
            return true;
        }
    }
    return false;
}

person.h

#pragma once
#include "Group.h"
#include <string>
#include <vector>

using namespace std;
// Person类的一个对象就是群中的一个成员 

class Group;
class Person {
    public:
        Person(void) = default;
        Person(const string &name, const string &id);
        Person(const Person& per) = default;
        Person& operator= (const Person& per);
        virtual ~Person(void) = default;

        const string& getName(void) const;
        const string& getId(void) const;
        void addGroup(Group &grp);
        void quitGroup(Group &grp);
        void sendMessage (const string &msg, Group &grp);
        void getMessageRecord (Group &grp);
//      void click();
    private:
        string m_name;
        string m_id;
        vector<Group *> m_group;
};

inline const string& Person::getName(void) const
{
    return m_name;
}
inline const string& Person::getId(void) const
{
    return m_id;
}

person.cpp

#include "Person.h"
#include <algorithm>
#include <iostream>
using namespace std;

Person::Person(const string& name, const string& id)
    : m_name(name), m_id(id)
{}

Person& Person::operator= (const Person &per)
{
    if (this != &per) {
        m_name = per.m_name;
        m_id = per.m_id;
        m_group = per.m_group;
    }
    return (*this);
}

void Person::addGroup(Group &grp)
{
    if (grp.onAddPerson(*this)) {
        m_group.push_back(&grp);
    }
    return ;
}
void Person::quitGroup(Group &grp)
{
    if (grp.onDelPerson(*this)) {
        auto it = find(m_group.begin(), m_group.end(), &grp); 
        m_group.erase(it);
    }
    return ;
}
void Person::sendMessage(const string& msg, Group &grp)
{
    grp.onReceiveMessage(msg, *this);
}
void Person::getMessageRecord(Group &grp)
{
    if (grp.checkPerson(*this)) {
        const vector<string>& v = grp.getRecord();
        for (int i = 0; i < v.size(); i ++) {
            cout << v[i] << endl;
        }
    }
    return ;
}

Decorator.h

#pragma once
#include "Group.h"

// Decorator 类就是设计模式中的decorator,是所有concrete decorator的父类
class Decorator: public Group {
    public:
        Decorator(Group &grp);
        Decorator(const Decorator &dct) = default;
        Decorator& operator=(const Decorator &dct);
        virtual ~Decorator(void) = default;

        virtual void onReceiveMessage(const string &msg, const Person &per) override;

        virtual void showRecord(void) override;

        virtual bool onAddPerson(const Person &per) override;
        virtual bool onDelPerson(const Person &per) override;   
        virtual bool checkPerson(const Person &per) const override;
        virtual const vector<string>& getRecord(void) const override;
    protected:
        Group &m_group;
        void action(void);
}; 

Decorator.cpp

#include "Decorator.h"

Decorator::Decorator(Group &grp) 
    : m_group(grp)
{}

Decorator& Decorator::operator=(const Decorator &dct)
{
    if (this != &dct) {
        m_group = dct.m_group;
    }
    return (*this);
}

void Decorator::action(void)
{}

bool Decorator::onAddPerson(const Person &per)
{
    return m_group.onAddPerson(per); 
}

bool Decorator::onDelPerson(const Person &per)
{
    return m_group.onDelPerson(per);
}

bool Decorator::checkPerson(const Person &per) const
{
    return m_group.checkPerson(per);
}

const vector<string>& Decorator::getRecord(void) const
{
    return m_group.getRecord();
}

void Decorator::onReceiveMessage(const string &msg, const Person &per)
{
    m_group.onReceiveMessage(msg, per);
} 

void Decorator::showRecord(void)
{
    m_group.showRecord();
}

Life.h

#pragma once 
#include "Decorator.h"

class Life final: public Decorator {
    public:
        Life(Group &grp);
        Life(const Life &lf) ;
        Life& operator= (const Life &lf);
        virtual ~Life(void) = default;

        virtual void onReceiveMessage(const string &msg, const Person &per) override;
        virtual void showRecord(void) override;

        virtual bool onAddPerson(const Person &per) override;
        virtual bool onDelPerson(const Person &per) override;   
        virtual bool checkPerson(const Person &per) const override;
        virtual const vector<string>& getRecord(void) const override;
    private:
        void action(void);

};

Life.cpp

#include "Life.h"
#include <iostream>
using namespace std;

Life::Life(Group &grp) 
    : Decorator(grp) 
{}

Life::Life(const Life &lf)
    : Decorator(lf)
{}

Life& Life::operator= (const Life &lf)
{
    if (this != &lf)
        Decorator::operator=(lf);
    return (*this);
}

void Life::action(void)
{
    cout << "吃饭" << endl;
    return ;
}

bool Life::onAddPerson(const Person &per)
{
    return m_group.onAddPerson(per); 
}

bool Life::onDelPerson(const Person &per)
{
    return m_group.onDelPerson(per);
}

bool Life::checkPerson(const Person &per) const
{
    return m_group.checkPerson(per);
}

const vector<string>& Life::getRecord(void) const
{
    return m_group.getRecord();
}

void Life::onReceiveMessage(const string &msg, const Person &per)
{
    m_group.onReceiveMessage("(生活)" + msg, per);
    action();
} 

void Life::showRecord(void)
{
    m_group.showRecord();
}

Business.h

#pragma once 
#include "Decorator.h"

class Business final: public Decorator {
    public:
        Business(Group &grp);
        Business(const Business &bns);
        Business& operator= (const Business &bns);
        virtual ~Business(void) = default;

        virtual void onReceiveMessage(const string &msg, const Person &per) override;
        virtual void showRecord(void) override;

        virtual bool onAddPerson(const Person &per);
        virtual bool onDelPerson(const Person &per);    
        virtual bool checkPerson(const Person &per) const;
        virtual const vector<string>& getRecord(void) const;
    private:
        void action(void);
};

Business.cpp

#include "Business.h"
#include <iostream>
using namespace std;

Business::Business(Group &grp) 
    : Decorator(grp) 
{}

Business::Business(const Business &bns)
    : Decorator(bns)
{}

Business& Business::operator= (const Business &bns)
{
    if (this != &bns)
        Decorator::operator=(bns);
    return (*this);
}

void Business::action(void)
{
    cout << "理财" << endl;
    return ;
}

bool Business::onAddPerson(const Person &per)
{
    return m_group.onAddPerson(per); 
}

bool Business::onDelPerson(const Person &per)
{
    return m_group.onDelPerson(per);
}

bool Business::checkPerson(const Person &per) const
{
    return m_group.checkPerson(per);
}

const vector<string>& Business::getRecord(void) const
{
    return m_group.getRecord();
}

void Business::onReceiveMessage(const string &msg, const Person &per)
{
    m_group.onReceiveMessage("(理财)" + msg, per);
    action();
} 

void Business::showRecord(void)
{
    m_group.showRecord();
}

Study.h

#pragma once 
#include "Decorator.h"

class Study final: public Decorator {
    public:
        Study(Group &grp);
        Study(const Study &sty);
        Study& operator= (const Study &sty);
        virtual ~Study(void) = default;

        virtual void onReceiveMessage(const string &msg, const Person &per) override;
        virtual void showRecord(void) override;

        virtual bool onAddPerson(const Person &per);
        virtual bool onDelPerson(const Person &per);    
        virtual bool checkPerson(const Person &per) const;
        virtual const vector<string>& getRecord(void) const;
    private:
        void action(void);
};

Study.cpp

#include "Study.h"
#include <iostream>
using namespace std;

Study::Study(Group &grp) 
    : Decorator(grp) 
{}

Study::Study(const Study &sty)
    : Decorator(sty)
{}

Study& Study::operator= (const Study &sty)
{
    if (this != &sty)
        Decorator::operator=(sty);
    return (*this);
}

void Study::action(void)
{
    cout << "学习" << endl;
    return ;
}

bool Study::onAddPerson(const Person &per)
{
    return m_group.onAddPerson(per); 
}

bool Study::onDelPerson(const Person &per)
{
    return m_group.onDelPerson(per);
}

bool Study::checkPerson(const Person &per) const
{
    return m_group.checkPerson(per);
}

const vector<string>& Study::getRecord(void) const
{
    return m_group.getRecord();
}

void Study::onReceiveMessage(const string &msg, const Person &per)
{
    m_group.onReceiveMessage("(学习)" + msg, per);
    action();
} 

void Study::showRecord(void)
{
    m_group.showRecord();
}

main.cpp

#include <iostream>
#include "Group.h"
#include "Decorator.h"
#include "Life.h"
#include "Business.h"
#include "Study.h"
#include <vector>
using namespace std;

int main(int argc, char** argv) 
{
    Person per("Jason", "12345");
    vector<Person *> vper;
    vper.push_back(&per);

    Group *p1 = new Group(vper);
    Group *p2 = new Life(*p1);
    Group *p3 = new Study(*p2);
    Group *p4 = new Business(*p3);

    per.sendMessage("hello!", *p4);
    cout << endl;
    per.sendMessage("hi!", *p2);
    cout << endl;
    per.getMessageRecord(*p1);
    cout << endl;
    per.getMessageRecord(*p4);
    cout << endl;
    return 0;
}

第六次实验报告

一、 题目分析
(1) 群信息共享的基本功能。
在群中有着不同的个体,每个个体都是一个对象,这个要求实际上就是对象之间的通讯,也就是群对象和每一个个体对象通讯。
(2) 群内有子群,任意个数任意深度组合,不同群消息处理不同,存在混合功能群。
我的理解,子群其实可以看作是同一个群的不同“频道”,对于每一个频道,群内都有一个机制使得对于不同频道的消息,使其有不同的处理,可以说,群组合了频道,对于混合频道,这个频道并不是既属于频道一又属于频道二,而是独立于频道一和频道二的新频道,但其又不是完全不相关的,新频道同时具有频道一和频道二的性质。
群中有子群,子群实现的第一种方式可以是对于每一个子群,从群这个类派生出所有不同子群的对象
(3) main中调用学习圈的消息处理和生活圈的消息处理
这个要求如题,main中调用就是了。

二、 解决思路
(1) 群与个体间的通信
正如上面所分析的,群信息共享最重要的就是群与个体之间的通信,为此,我定义了Person类和Group类,其中,Person类中包含着Person所加入的Group的指针,Group类中保存着所有加入这个Group的Person的指针。我把Group这个类看成类似于server的存在,其不仅存储着消息记录,而且对于在Group中的Person对象的sendMessage和getMessageRecord的两个请求函数,有着onReceiveMessage和getRecord的消息处理函数,分别记录下message和发送record给person,从而实现了群和个体的通信。(addGroup、quitGroup和onAddPerson、onDelPerson同理)
(2) 核心:群与子群的关系如何设计
从上面分析的来看,群组合了频道(子群),如果我们从群这个类派生出频道类,那么群必然要包含若干个其派生类的对象(指针),这是很别扭的,其次,是存在混合频道的,这样的话按照前面的思路,我们就要从频道类中再次派生出派生类,而且还是多重继承,如果混合的性质越多,那么类的个数的增长是指数级别的,这是绝不能忍受的。
换一种思路,如果把频道类型当作群的一种属性,单纯的群看作是一个无属性的频道,这个频道包含着若干个有属性的频道,这样会比第一种方法好很多,但是还是无法解决一个问题,就是当频道类型很多的时候,群这个类会变的十分冗杂,不易于维护,十分不优美。如果频道只有学习生活理财这三个属性,这种方法不失为一种选择,但是现实往往并不是这样的。
这时我想到了装饰模式,想想看,既然群可以是看作是无属性的频道,那么频道不就是有“装饰”的群吗?当遇到多属性的频道时,就在原有的频道上再加一道“装饰”就可以了。同时设计简洁美观,易于维护。从装饰模式的UML类图看,这次的设计只有一种concrete component,因此,我们把类图中的component和concrete component合二为一,就是Group类。并定义Decorator类,继承自Group类,这里的继承目的是可以用Group类指针管理Decorator及其后代,而不是行为上的继承,因此在Decorator的构造中,我并没有理会基类中Group的部分。然后定义concrete decorator:Life、Study和Business。

三、 优点与缺点
优点:
a) 完成了题目所有要求
b) 使用了装饰模式,正确的剖析了类与类之间的关系
c) 实现了加群退群等一些小功能
缺点:
a) 注重了装饰模式的体现,程序逻辑比较简单

我觉得这次实验的题目出的非常好,让我对面向对象有了全新的认识,OOP并不只是写几个类几个模版的事情,它确确实实是一种思想,通过我们学习的语法和OOP提供的工具,有着比面向过程更强的表达能力。设计模式真的是很巧妙啊!虽然好理解,但实现的过程却并不简单。之后工程上遇到的问题也和这次一样,不会是看一眼就知道如何解决的,动手之前的思考和建模甚至比编码本身更重要,这次实验让我深深体会到了这一点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值