装饰模式简介(内容来自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提供的工具,有着比面向过程更强的表达能力。设计模式真的是很巧妙啊!虽然好理解,但实现的过程却并不简单。之后工程上遇到的问题也和这次一样,不会是看一眼就知道如何解决的,动手之前的思考和建模甚至比编码本身更重要,这次实验让我深深体会到了这一点。