首页 > 其他 > 详细

第31章 新的设计模式

时间:2016-07-21 23:45:38      阅读:215      评论:0      收藏:0      [点我收藏+]

31.1 规格模式(Specitification Pattern)

31.1.1 查询筛选条件

(1)场景:根据条件从数据库的用户表中筛选出对象

(2)存在问题

  ①findUserByAgeThan和findUserByName两个方法中除了if后面的判断条件不同,其他地方完全一样

  ②这两个程序中唯一的变化点就是条件语句可以将这里封装起来,后面的例子会设计一个规格类,用于封装整个条件语句。

【编程实验】根据条件筛选用户表数据

//新设计模式——规格模式
//实例:实现不同条件的查询(不使用规格模式)
//存在问题:
//1. findUserByAgeThan和findUserByName两个方法中除了if后面的判断条件
//不同,其他地方完全一样
//2. 这两个程序中唯一的变化点就是条件语句,可以将这里封装起来,后面的
//   例子会设计一个规格类,用于封装整个条件语句
#include <iostream>
#include <string>
#include <vector>
#include <sstream>

using namespace std;
//用户类
class User
{
private:
    string name; //姓名
    int age;     //年龄
public:
    User(string name, int age)
    {
        this->name = name;
        this->age = age;
    }

    string getName(){return name;}
    void setName(string value){name = value;}

    int getAge(){return age;}
    void setAge(int value){age = value;}

    string toString()
    {
        ostringstream oss;
        oss << age;
        string ret = "用户名:" + name + "\t年龄:" + oss.str();
        return ret;
    }
};

//用户操作对象接口
class IUserProvider
{
public:
    virtual vector<User*>* findUserByName(string name) = 0;
    virtual vector<User*>* findUserByAgeThan(int age) = 0;
};

//用户操作类
class UserProvider : public IUserProvider
{
private:
    vector<User*>* userList;
public:
    UserProvider(vector<User*>* userList)
    {
        this->userList = userList;
    }

    //年龄大于指定年龄
    vector<User*>* findUserByAgeThan(int age)
    {
        vector<User*>* ul = new vector<User*>();
        vector<User*>::iterator iter = userList->begin();
        for(;iter != userList->end(); ++iter)
        {
            if((*iter)->getAge() > age)  //与findUserByName唯一的不同
            {
                ul->push_back((*iter));
            }
        }
        return ul;
    }
    //姓名等于指定姓名的用户
    vector<User*>* findUserByName(string name)
    {
        vector<User*>* ul = new vector<User*>();
        vector<User*>::iterator iter = userList->begin();
        for(;iter != userList->end(); ++iter)
        {
            if((*iter)->getName() == name) //与findUserByAgeThan唯一的不同
            {
                ul->push_back((*iter));
            }
        }
        return ul;
    }
};

void createUsers(vector<User*>& userList)
{
    userList.push_back( new User("苏三",3) );
    userList.push_back( new User("牛二",8) );
    userList.push_back( new User("张三",10) );
    userList.push_back( new User("李四",15) );
    userList.push_back( new User("王五",18) );
    userList.push_back( new User("赵六",20) );
    userList.push_back( new User("马七",25) );
    userList.push_back( new User("杨八",30) );
    userList.push_back( new User("侯九",35) );
    userList.push_back( new User("布十",40) );
}

void delUsers(vector<User*>& userList)
{
    vector<User*>::iterator iter = userList.begin();
    while (iter != userList.end())
    {
        delete (*iter);
        ++iter;
    }

    userList.clear();
}

void showUsers(vector<User*>& userList)
{
    vector<User*>::iterator iter = userList.begin();
    while (iter != userList.end())
    {
        cout << (*iter)->toString() <<endl;
        ++iter;
    }
}

int main()
{
    //首先初始化一批用户
    vector<User*> userList;
    createUsers(userList);

    //定义一个用户查询类
    IUserProvider* userProvider = new UserProvider(&userList);
    //查询并打印年龄大于20岁的用户
    vector<User*>* ul = userProvider->findUserByAgeThan(20);
    showUsers(*ul);

    ul->clear();
    delete ul;

    delUsers(userList);

    return 0;
};
/*输出结果:
用户名:马七     年龄:25
用户名:杨八     年龄:30
用户名:侯九     年龄:35
用户名:布十     年龄:40
*/

31.1.2 解决方案

(1)规格模式

(2)类图

技术分享 

  ①规格书接口中增加了与或非操作,返回值为规格书类型这样设计的目的是为了连续调用。

  ②由于与或非是不可扩展的操作,这部分是不可能发生变化的部分。因此,这里出现了父类对子类的依赖,这种情况只有在非常明确不会发生变化的场景中。

【编程实验】

技术分享

//User.h

技术分享
#pragma once
#include <string>
#include <sstream>
using namespace std;

//************************************************辅助类*****************************************
//用户类
class User
{
private:
    string name; //姓名
    int age;     //年龄
public:
    User(string name, int age)
    {
        this->name = name;
        this->age = age;
    }

    string getName(){return name;}
    void setName(string value){name = value;}

    int getAge(){return age;}
    void setAge(int value){age = value;}

    string toString()
    {
        ostringstream oss;
        oss << age;
        string ret = "用户名:" + name + "\t年龄:" + oss.str();
        return ret;
    }
};
View Code

//Specification.h

#pragma once
#include "User.h"
//**************************************定义规格接口*****************************
//规格书接口(支持与或非)
class ISpecification
{
public:
    //候选者是否满足要求
    virtual bool isSatisfiedBy(User* user) = 0;
    //and操作
    virtual ISpecification* andOp(ISpecification* spec) = 0;
    //or操作
    virtual ISpecification* orOp(ISpecification* spec) = 0;
    //not操作
    virtual ISpecification* notOp() = 0;

    virtual ~ISpecification(){}
};

//组合规格书
class CompositeSpecification : public ISpecification
{
public:
    ISpecification* andOp(ISpecification* spec);
    ISpecification* orOp(ISpecification* spec);
    ISpecification* notOp();
};

//and操作
class AndSpecification : public CompositeSpecification
{
private:
    ISpecification* left;
    ISpecification* right;
public:
    AndSpecification(ISpecification* left, ISpecification* right);

    //进行and运算
    bool isSatisfiedBy(User* user);
};

//and操作
class OrSpecification : public CompositeSpecification
{
private:
    ISpecification* left;
    ISpecification* right;
public:
    OrSpecification(ISpecification* left, ISpecification* right);

    //进行or运算
    bool isSatisfiedBy(User* user);
};

//not操作
class NotSpecification : public CompositeSpecification
{
private:
    ISpecification* spec;
public:
    NotSpecification(ISpecification* spec);
    //进行not运算
    bool isSatisfiedBy(User* user);
};

//姓名相同的规格书
class UserByNameEqual : public CompositeSpecification
{
private:
    string name; //姓名
public:
    UserByNameEqual(string name);

    //检验用户是否满足条件
    bool isSatisfiedBy(User* user);
};

//年龄大于20岁的规格书
class UserByAgeThan : public CompositeSpecification
{
private:
    int age; //年龄
public:
    UserByAgeThan(int age);

    //检验用户是否满足条件
    bool isSatisfiedBy(User* user);
};

//like规格书
class UserNameLike: public CompositeSpecification
{
private:
    string name; //姓名
public:
    UserNameLike(string name);

    //检验用户是否满足条件
    bool isSatisfiedBy(User* user);
};

//Specification.cpp

#include "Specification.h"
//****************************CompositeSpecification类***********************
//and操作
ISpecification* CompositeSpecification::andOp(ISpecification* spec)
{
    return new AndSpecification(this, spec);
};
//or操作
ISpecification* CompositeSpecification::orOp(ISpecification* spec)
{
    return new OrSpecification(this, spec);
};
//not操作
ISpecification* CompositeSpecification::notOp()
{
    return new NotSpecification(this);
};

//****************************AndSpecification***********************
//and操作
AndSpecification::AndSpecification(ISpecification* left, ISpecification* right)
{
    this->left = left;
    this->right = right;
}

//进行and运算
bool AndSpecification::isSatisfiedBy(User* user)
{
    return left->isSatisfiedBy(user) && right->isSatisfiedBy(user);
}

//****************************OrSpecification***********************
//and操作
OrSpecification::OrSpecification(ISpecification* left, ISpecification* right)
{
    this->left = left;
    this->right = right;
}

//进行or运算
bool OrSpecification::isSatisfiedBy(User* user)
{
    return left->isSatisfiedBy(user) || right->isSatisfiedBy(user);
}

//****************************OrSpecification***********************
//not操作
NotSpecification::NotSpecification(ISpecification* spec)
{
     this->spec = spec;
}
//进行not运算
bool NotSpecification::isSatisfiedBy(User* user)
{
    return ! spec->isSatisfiedBy(user);
}

//****************************UserByNameEqual***********************
//姓名相同的规格书
UserByNameEqual::UserByNameEqual(string name)
{
    this->name = name;
}

//检验用户是否满足条件
bool UserByNameEqual::isSatisfiedBy(User* user)
{
     return (user->getName() == name);
}

//****************************UserByNameEqual***********************
//年龄大于20岁的规格书
UserByAgeThan::UserByAgeThan(int age)
{
    this->age = age;
}

//检验用户是否满足条件
bool UserByAgeThan::isSatisfiedBy(User* user)
{
    return (user->getAge() >= age);
}

//****************************UserNameLike***********************
//like规格书
UserNameLike::UserNameLike(string name)
{
    this->name = name;
}

//检验用户是否满足条件
bool UserNameLike::isSatisfiedBy(User* user)
{
    int nPos = (user->getName()).find(name);
    return (nPos >=0);
}

//main.cpp

//新设计模式——规格模式
//实例:实现不同条件的查询(使用规格模式)
//说明: 本例除了可以进行简单条件语句的查询,也可以复合语
//  包含与、或、非等
#include <iostream>
#include <string>
#include <vector>
#include "Specification.h"
#include "User.h"
using namespace std;


//用户操作对象接口
class IUserProvider
{
public:
    virtual vector<User*>* findUser(ISpecification* spec) = 0;

    virtual ~IUserProvider(){}
};

//用户操作类
class UserProvider : public IUserProvider
{
private:
    vector<User*>* userList;
public:
    UserProvider(vector<User*>* userList)
    {
        this->userList = userList;
    }

    //查询指定规格的用户
    vector<User*>* findUser(ISpecification* spec)
    {
        vector<User*>* ul = new vector<User*>();
        vector<User*>::iterator iter = userList->begin();
        for(;iter != userList->end(); ++iter)
        {
            if(spec->isSatisfiedBy(*iter))  //注意,条件语句被规格书所替代
            {
                ul->push_back((*iter));
            }
        }
        return ul;
    }
};

//**********************************************辅助函数***********************************
void createUsers(vector<User*>& userList)
{
    userList.push_back( new User("苏三",3) );
    userList.push_back( new User("牛二",8) );
    userList.push_back( new User("张三",10) );
    userList.push_back( new User("李四",15) );
    userList.push_back( new User("王五",18) );
    userList.push_back( new User("赵六",20) );
    userList.push_back( new User("马七",25) );
    userList.push_back( new User("杨八",30) );
    userList.push_back( new User("侯九",35) );
    userList.push_back( new User("布十",40) );
    userList.push_back( new User("苏国庆",23) );
    userList.push_back( new User("国庆牛",82) );
    userList.push_back( new User("张国庆三",10) );
}

void delUsers(vector<User*>& userList)
{
    vector<User*>::iterator iter = userList.begin();
    while (iter != userList.end())
    {
        delete (*iter);
        ++iter;
    }

    userList.clear();
}

void showUsers(vector<User*>& userList)
{
    vector<User*>::iterator iter = userList.begin();
    while (iter != userList.end())
    {
        cout << (*iter)->toString() <<endl;
        ++iter;
    }
}

int main()
{
    //首先初始化一批用户
    vector<User*> userList;
    createUsers(userList);

    //定义一个用户查询类
    IUserProvider* userProvider = new UserProvider(&userList);
    //查询并打印年龄大于20岁的用户
    ISpecification* spec1 = new UserByAgeThan(20);
    ISpecification* spec2 = new UserNameLike("国庆");
    ISpecification* spec3 = spec1->andOp(spec2);
    vector<User*>* ul = userProvider->findUser(spec3);
    showUsers(*ul);

    ul->clear();

    delete spec1;
    delete spec2;
    delete spec3;
    delete ul;
    delete userProvider;

    delUsers(userList);

    return 0;
};
/*输出结果:
用户名:苏国庆   年龄:23
用户名:国庆牛   年龄:82
*/

31.1.3 小结

(1)基类代表所有规格书,它的目的是描述一个完整的、可组合的规格书,它代表的是一个整体,其下的And、Or、Not规格书、年龄大于基准年龄等规格书是一个个真实的实现,也就是一个局部,这是组合模式的一种特殊应用。

(2)每个规格书又是一个个策略,它完成一系列逻辑的封装,这些策略可以相互替换。

(3规格模式可巧妙实现对象筛选功能。在类似于多个对象中筛选查找,或者业务规则不适于放在任何己有实体或值对象中,而且规则变化和组合会掩盖那些领域对象的基本含义,可以考虑该模式

(4)规格模式中有个很严重的问题就是父类依赖子类,这种情景只有在非常明确不会发生变化的场景中存在,它不具备扩展性,是一种固化而不可变化的结构。一般面向对象设计中应该尽量避免。

第31章 新的设计模式

原文:http://www.cnblogs.com/5iedu/p/5693374.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!