过滤器模式(C++实现)之帮你选个男朋友

过滤器模式(Filter Pattern)

过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。这种这么官方的介绍当然是我从菜鸟教程复制过来的——过滤器模式|菜鸟教程
那就再谈一谈我自己的见解吧,感觉那些购物app(比如说淘宝)的筛选功能应该就是过滤器模式的教科书级实现吧。你可以筛选价格、风格、产地等等,这不就是一个个过滤器的实现吗?!然后再加上组合过滤器的实现,哇,筛选功能出来了诶

UML图

在这里插入图片描述
creiteria是所有过滤器的基类,与组合过滤器的关系应该算是聚合吧
至于boy,当然就是你的对象啊,狗头.jpg

代码实现

boy.h

#ifndef _BOY_
#define _BOY_

#include <string>
#include <iostream>
#include "stdio.h"

using namespace std;

class boy
{
private:
    string m_name;
    double m_weight;
    double m_height;
    string m_appearance;

public:
    boy(string name, double weight, double height, string appearance)
    {
        m_name = name;
        m_weight = weight;
        m_height = height;
        m_appearance = appearance;
    }
    bool operator < (const boy& b)
    {
        return this->m_name < b.get_name();
    }
    bool operator == (const boy& b)
    {
        return this->m_name == b.get_name();
    }
    string get_appearance()
    {
        return this->m_appearance;
    }
    double get_weight()
    {
        return this->m_weight;
    }
    double get_height()
    {
        return this->m_height;
    }
    string get_name() const
    {
        return this->m_name;
    }
    string show_me()
    {
        char describation[128] = {0};
        snprintf(describation, sizeof(describation) - 1,
                "name:%s\n%.2lfcm\n%.2lfkg\nappreance:%s\n", m_name.c_str(), m_height,
                m_weight, m_appearance.c_str());
        return describation;
    }
};
#endif

criteria.h

#ifndef _CRITERIA_
#define _CRITERIA_

#include "boy.h"
#include <string>
#include <list>
#include <iostream>
#include <math.h>
#include <algorithm>

using namespace std;

const double g_d_value = 1e-6;

class criteria
{
public:
    virtual list<boy> filter(list<boy> filter_list) = 0;
};

class criteria_handsome:public criteria
{
private:
    list<boy> m_list;

public:
    virtual list<boy> filter(list<boy> filter_list)
    {
        m_list.clear();
        list<boy>::iterator it;
        for (it = filter_list.begin(); it != filter_list.end(); it++)
        {
            if (it->get_appearance() == "handsome")
            {
                m_list.push_back(*it);
            }
        }
        return this->m_list;
    }
};

class criteria_higher:public criteria
{
private:
    list<boy> m_list;
    double m_lowest_height;

public:
    criteria_higher(double lowest_height)
    {
        m_lowest_height = lowest_height;
    }
    virtual list<boy> filter(list<boy> filter_list)
    {
        m_list.clear();
        list<boy>::iterator it;
        for (it = filter_list.begin(); it != filter_list.end(); it++)
        {
            if (it->get_height() - m_lowest_height >= g_d_value)
            {
                m_list.push_back(*it);
            }
        }
        return this->m_list;
    }
};

class or_criteria
{
private:
    list<boy> m_list;
    list<shared_ptr<criteria>> m_criteria_list;

public:
    list<boy> filter(list<boy> filter_list)
    {
        m_list.clear();
        list<shared_ptr<criteria>>::iterator it;
        for (it = m_criteria_list.begin(); it != m_criteria_list.end(); it++)
        {
            m_list.merge((*it)->filter(filter_list));
        }
        //||过滤器会累积重复的对象,去重
        m_list.sort();
        //unique指向不重复序列的下一个对象
        m_list.erase(unique(m_list.begin(), m_list.end()), m_list.end());
        return m_list;
    }
    void add_criteria(shared_ptr<criteria> filter)
    {
        if (filter == NULL)
            return;
        m_criteria_list.push_back(filter);
        return;
    }
};

class and_criteria
{
private:
    list<boy> m_list;
    list<shared_ptr<criteria>> m_criteria_list;

public:
    list<boy> filter(list<boy> filter_list)
    {
        m_list = filter_list;
        list<shared_ptr<criteria>>::iterator it;
        for (it = m_criteria_list.begin(); it != m_criteria_list.end(); it++)
        {
            m_list = (*it)->filter(m_list);
        }
        return m_list;
    }
    void add_criteria(shared_ptr<criteria> filter)
    {
        if (filter == NULL)
            return;
        m_criteria_list.push_back(filter);
        return;
    }
};
#endif
filter_pattern.cpp

#include <iostream>
#include <memory>
#include "criteria.h"
#include "boy.h"

using namespace std;

int main(int argc, const char *argv[])
{
    boy wyf("wyf", 85, 187.5, "handsome");
    boy lh("lh", 65.3, 175.5, "handsome");
    boy answer("answer", 75, 183, "handsome");
    boy your_boy_friend("xxx", 100, 180, "ugly");
    list<boy> list_boy;
    list_boy.push_back(wyf);
    list_boy.push_back(lh);
    list_boy.push_back(answer);
    list_boy.push_back(your_boy_friend);

    //单一过滤器
    shared_ptr<criteria> height_filter(new criteria_higher(178));
    list<boy> height_filter_boy = height_filter->filter(list_boy);
    list<boy>::iterator it;
    cout << "the list boy after height filter:" << endl;
    for (it = height_filter_boy.begin(); it != height_filter_boy.end(); it++)
    {
        cout << it->show_me() << endl;
    }

    //&&过滤器
    shared_ptr<criteria> face_filter(new criteria_handsome);
    and_criteria and_filter;
    and_filter.add_criteria(height_filter);
    and_filter.add_criteria(face_filter);

    list<boy> and_filter_boy = and_filter.filter(list_boy);
    cout << "the list boy after and filter:" << endl;
    for (it = and_filter_boy.begin(); it != and_filter_boy.end(); it++)
    {
        cout << it->show_me() << endl;
    }

    //||过滤器
    or_criteria or_filter;
    or_filter.add_criteria(height_filter);
    or_filter.add_criteria(face_filter);
    list<boy> or_filter_boy = or_filter.filter(list_boy);
    cout << "the list boy after or filter:" << endl;
    for (it = or_filter_boy.begin(); it != or_filter_boy.end(); it++)
    {
        cout << it->show_me() << endl;
    }
    return 0;
}

在写demo的时候试了下C++智能指针和list容器中的元素是智能指针share_ptr,推荐使用7.3版本的gcc,体验最新版的C++

结果

[root@bogon filter_pattern]# g++ filter_pattern.cpp 
[root@bogon filter_pattern]# ./a.out
the list boy after height filter:
name:wyf
187.50cm
85.00kg
appreance:handsome

name:answer
183.00cm
75.00kg
appreance:handsome

name:xxx
180.00cm
100.00kg
appreance:ugly

the list boy after and filter:
name:wyf
187.50cm
85.00kg
appreance:handsome

name:answer
183.00cm
75.00kg
appreance:handsome

the list boy after or filter:
name:answer
183.00cm
75.00kg
appreance:handsome

name:lh
175.50cm
65.30kg
appreance:handsome

name:wyf
187.50cm
85.00kg
appreance:handsome

name:xxx
180.00cm
100.00kg
appreance:ugly


过滤了下,最丑的当然是你的对象啊,狗头.jpg

写demo过程中碰见的几个问题

  1. 组合过滤器,||过滤器,多次过滤一组对象,会得到重复的对象诶,怎么搞?

那就把链表中的对象去重下吧,使用unique函数iterator unique(iterator it_1,iterator it_2,bool MyFunc);,注意该函数的头文件#include <algorithm>,unique的实现是将链表中所有相邻并且相同的元素往后移,所以使用unique前先list.sort,然后再配合list.erase使用就好。

  1. list容器的元素是自定义对象,编译过程中容易遇到下面的问题:

在这里插入图片描述
这是编译器不知道怎么比较你写的自定义对象了,所以你的自定义类中需要对一些==等符号去重载实现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值