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

  摘要

  《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

  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;
}

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

  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;
}
时间: 2024-12-20 01:04:39

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

Spring 实现两种设计模式:工厂模式和单态模式

在Spring 中大量使用的以下两种设计模式:工厂模式和单态模式. 工厂模式可将Java 对象的调用者从被调用者的实现逻辑中分离出来,调用者只需关心被调用者必须满足的规则(接口) ,而不必关心实例的具体实现过程.这是面向接口编程的优势,能提高程序的解耦,避免所有的类以硬编码方式耦合在一起. 如果所有的类直接耦合,极易形成"骨牌效应",假如B 类调用了A 类,一旦A 类需要修改,则B 类也需要修改:假如C 类调用了B 类,则C 类也需要修改......依次类推,从而导致整个系统都需要改写

23种设计模式(6):模版方法模式

定义:定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤. 类型:行为类模式. 类图: 事实上,模版方法是编程中一个经常用到的模式.先来看一个例子,某日,程序员A拿到一个任务:给定一个整数数组,把数组中的数由小到大排序,然后把排序之后的结果打印出来.经过分析之后,这个任务大体上可分为两部分,排序和打印,打印功能好实现,排序就有点麻烦了.但是A有办法,先把打印功能完成,排序功能另找人做. abstract class AbstractS

二十三种设计模式[21] - 策略模式(Strategy Pattern)

前言 策略模式,对象行为型模式的一种.在<设计模式 - 可复用的面向对象软件>一书中将之描述为" 定义一些列的算法,把它们一个个封装起来,并且使它们可相互替换.使得算法可以独立于使用它的客户而变化 ". 也就是说通过策略模式,我们能够将算法与其调用者分离成相对独立的个体,降低维护成本,使代码更加优雅. 场景 就拿数据的搜索来说,可以简单的分为模糊搜索和精确搜索.在开发这个功能时,可能会写出如下代码. public List<string> Search(stri

二十四种设计模式:策略模式(Strategy Pattern)

策略模式(Strategy Pattern) 介绍定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例有一个Message实体类,对它的操作有Insert()和Get()方法,持久化数据在SqlServer数据库中或Xml文件里(两种可互换的算法).由客户端决定使用哪种算法. MessageModel using System; using System.Collections.Generic; using System.Text; na

23种设计模式之——策略模式

什么是策略模式? 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 什么时候去使用策略模式? 策略模式就是用来封装算法的,但是在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性. 适用的场景? 1.如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为. 2.一个系统需要动态地在几

23种设计模式之策略模式(Strategy)

策略模式是一种对象的行为型模式,定义一系列算法,并将每一个算法封装起来,并让它们可以相互替换.策略模式比算法独立于使用它的客户而变化,其目的是将行为和环境分隔,当出现新的行为时,只需要实现新的策略类. 优点: 1)另一种子类化方法. 2)在类自身中定义了每一个行为,这样就减少了条件语句. 3)更容易扩展模型.在不对应用程序进行代码修改的情况下,使该模式具有新的行为. 使用场景: 1)许多相关类只是在行为方面有所区别. 2)许多算法的不同变体. 3)算法使用客户端未知的数据. Strategy 模

java23种设计模式之一: 策略模式

由于最近在研究学习设计模式,我会用自己的理解方式来表述对设计模式的学习和认识,通过最常用.好记的案例来记住和使用设计模式,希望对设计代码方面有所提高和改进. 一.应用背景     在软件开发中常常遇到这种情况,实现某一个功能有多种算法或者策略,我们可以根据应用场景的不同选择不同的算法或者策略来完成该功能.把一个类(A)中经常改变或者将来可能改变的部分提取出来,作为一个接口(B),然后在类(A)中包含这个接口(B),这样类(A)的实例在运行时就可以随意调用实现了这个接口的类(C)的行为.比如定义一

007 - 策略模式对模版方法设计模式改进

如果我只需要获取User 的name 怎么办? 需要在重新创建一个方法 单独获取方法吗? 那可以通过返回User 对象 这种方法 虽然说可以, 但不怎么符合设计规范 我需要什么样的数据, 你应该就返回给我什么数据, 而不是需要我在处理而且当数据量的时候 会影响网络数据的传输性能 public String findName(int id){     String sql = "select name from user where id = ?";     Object[] args 

两种设计模式和XML解析

两种设计模式 1.单例模式 模式的保证步骤:单例(是说在一个类中只能有一个对象)三条件 1.1类构造设置私有  private  Play() { } 1.2 定义一个私有的静态的  类类型  变量 private static Play play; 1.3 定义共有的 静态的 并且 返回值类型为 类类型 的方法 public static Play GetInstance() { if(play==null) { play=new Play(); } retuen play; } 2.简单工厂