一道题采用两种设计模式:对比策略模式和模版方法

  摘要

  《C++ Primer》习题14.38和14.39分别采用策略模式、模版方法解决问题。

  问题

  《C++ Primer 5th》习题 14.38 : 编写一个类令其检查某个给定的 string 对象的长度是否与一个阀值相等。使用该对象编写程序,统计并报告输入的文件中长度为 1 的单词有多少个、长度为 2 的单词有多少个、......、长度为 10 的单词有多少个。

  《C++ Primer 5th》习题 14.39 : 修改上一题的程序令其报告长度在 1 至 9 之间的单词有多少个、长度在 10 以上的单词又有多少个。

  解法一 模版方法 Template Method

  UML 类图如下:

  Solution 代码如下:

template <typename T>
struct Solution {
    Solution(int n) :val(n) {}
    virtual ~Solution() {}
    virtual void operator() (const T& e) = 0;
    unsigned int val;
    int times = 0;
};

  EqualSolution 代码如下:

template <typename T>
struct EqualSolution : public Solution<T>{
    Solution::Solution;
    virtual void operator() (const T& e) override {
        if (e.size() == this->val)
            this->times++;
    }
};

  GreaterSolution 代码如下:

template <typename T>
struct GreaterSolution : public Solution<T> {
    Solution::Solution;
    virtual void operator() (const T& e) override {
        if (e.size() > this->val)
            this->times++;
    }
};

  LesserSolution 代码如下:

template <typename T>
struct LesserSolution : public Solution<T> {
    Solution::Solution;
    virtual void operator() (const T& e) override {
        if (e.size() < this->val)
            this->times++;
    }
};

  客户端调用代码如下:

int main()
{
    vector<string> v{ "a", "b", "abc", "abcd", "abcde", "abcdef" };

    Solution<string>* es = new EqualSolution<string>(1);
    Solution<string>* ls = new LesserSolution<string>(5);
    Solution<string>* gs = new GreaterSolution<string>(5);

    for (auto &e : v) {
        es->operator()(e);
        ls->operator()(e);
        gs->operator()(e);
    }

    cout << "长度等于 1 的有几个: " << es->times << endl;
    cout << "长度小于 5 的有几个: " << ls->times << endl;
    cout << "长度大于 5 的有几个: " << gs->times << endl;

    return 0;
}

  解法二 策略方法 + 工厂方法

  UML类图如下:

  

  CompareStrategy 代码如下:

struct CompareStrategy {
    virtual void operator() (const string& s, const unsigned int val, unsigned int& times) = 0;
    virtual ~CompareStrategy() {};
};

  EqualStrategy 代码如下:

struct EqualStrategy : public CompareStrategy {
    virtual void operator() (const string& s, const unsigned int val, unsigned int& times) {
        if (s.size() == val)
            times++;
    }
};

  GreaterStrategy 代码如下:

struct GreaterStrategy : public CompareStrategy {
    virtual void operator() (const string& s, const unsigned int val, unsigned int& times) {
        if (s.size() > val)
            times++;
    }
};

  LesserStrategy 代码如下:

struct LesserStrategy : public CompareStrategy {
    virtual void operator() (const string& s, const unsigned int val, unsigned int& times) {
        if (s.size() < val)
            times++;
    }
};

  Context 代码如下:

struct Context {
    CompareStrategy *strategy;
    unsigned int times = 0;
    unsigned int val = 0;
    void operator() (const string& s) {
        strategy->operator() (s, val, times);
    }
    Context(char type, int v) : val(v) {  
        switch (type)    // 简单工厂模式
        {
        case 'e': // equal
            strategy = new EqualStrategy();
            break;
        case 'g': // greater
            strategy = new GreaterStrategy();
            break;
        case 'l': // lesser
            strategy = new LesserStrategy();
            break;
        default:
            cout << "不存在该方法" << endl;
            exit(-1);
            break;
        }
    }
};

  客户端调用代码如下:

int main() {
    vector<string> v{ "1", "12", "123", "1234" };

    Context c1('e', 3);
    Context c2('g', 3);
    Context c3('l', 3);

    for (auto &e : v) {
        c1(e);
        c2(e);
        c3(e);
    }

    cout << c1.times << endl;
    cout << c2.times << endl;
    cout << c3.times << endl;
    return 0;
}

   总结

  两种模式下,耦合度都不高,但是采用策略模式更合乎人类的思维。

  所以这道题,策略模式更适用。

原文地址:https://www.cnblogs.com/fengyubo/p/4878824.html