策略模式笔记

UML类图入下 :

解决的问题 :

  • 减少代码中的 if  else 语句
  • 简化了单元测试
    • 不同算法独自成类,可以分别进行测试

注意点:

  • 可以用简单工厂结合策略模式

算法对象接口为Alorithm.hpp

#ifndef _ALGORITHM_H_ 
#define _ALGORITHM_H_ 

class Algorithm {
public:
    Algorithm() { };
    ~Algorithm() { };

    virtual double getMinDist(int x1, int y1, int x2, int y2) { return 1.0; }
};
#endif	// _ALGORITHM_H_

两个继承了Algorithm的子类DijkstraSpfa

  • 可以分别编写测试类DijkstraTestSpfaTest,简化了测试
#ifndef _DIJKSTRA_H 
#define _DIJKSTRA_H 
#include "Algorithm.hpp"

class Dijkstra : public Algorithm {
public:
    Dijkstra() { }
    ~Dijkstra() { }

    virtual double getMinDist(int x1, int y1, int x2, int y2) { return 1.0; }
};
#endif	// _DIJKSTRA_H


#ifndef _SPFA_H 
#define _SPFA_H 
#include "Algorithm.hpp"

class Spfa : public Algorithm {
public:
    Spfa() { };
    ~Spfa() { };

    virtual double getMinDist(int x1, int y1, int x2, int y2) { return 1.0; }
};

#endif	// _SPFA_H

一个AlgoContext类可以拥有Algorithm对象父类指针

并对外暴露一个调用接口计算的方法

#ifndef _ALGOCONTEXT_H 
#define _ALGOCONTEXT_H 

#include "Algorithm.hpp"

class AlgoContext {
public:

    // Context可以拥有一个或多个接口指针
    Algorithm* algo;

    AlgoContext(Algorithm* _algo) { this->algo = _algo; }
    ~AlgoContext() { }

    double getResult(int x1, int y1, int x2, int y2) {
        // context会根据不同的algo子类调用不同的算法求最短路

        return this->algo->getMinDist(x1, y1, x2, y2);
    }
};


#endif	// _ALGOCONTEXT_H

最后是调用方main函数里调用,但是这里有一个类的创建问题

  • 可以使用简单工厂实现解耦
  • 书上推荐使用工厂+策略模式结合的方法(不需要工厂类)
// 未结合工厂  调用方需要一大堆if else
#include "AlgoContext.hpp"
#include "Dijkstra.hpp"
#include "Spfa.hpp"

signed main() {

    AlgoContext context(NULL);

    // 这里的对象创建问题可以用 “简单工厂” 模式解决
    // 书上引入了 "策略模式+简单工厂"的结合模式(不需要工厂类)
    if (edgeCount > 2e5) {
        // 稠密图用Dijkstra+堆优化
        context.algo = new Dijkstra();
    }

    if (edgeCount < 2e5) {
        // 稀疏图用Spfa
        context.algo = new Spfa();
    }

    double result = context.getResult(0, 0, 100, 100);
    cout << "最短路长度 : " << result << endl;

    return 0;
}

策略模式结合简单工厂模式的代码如下

AlgoContext

  • // 策略模式结合简单工厂
    class AlgoContext {
    public:
    
        // Context可以拥有一个或多个接口指针
        Algorithm* algo;
    
        enum TYPE_ALGORITHM { TYPE_DIJKSTRA, TYPE_SPFA };
    
        AlgoContext(int edgeCount) { 
            this->algo = AlgoContext::getInstance(edgeCount);
        }
        ~AlgoContext() { }
        
        static Algorithm* getInstance(int edgeCount) {
            // 根据入参不同 new 出不同的对象 (简单工厂)
            if (edgeCount > 2e5) { return new Dijkstra(); }
            if (edgeCount <= 2e5) { return new Spfa(); }
            return 0;
        }
    
        double getResult(int x1, int y1, int x2, int y2) {
            // context会根据不同的algo子类调用不同的算法求最短路
            return this->algo->getMinDist(x1, y1, x2, y2);
        }
    };
    

结合简单工厂后的main调用方只需要2行代码(调用方简化了一堆if else)

  • 如果调用方是界面类,那么 算法和界面 就解耦了

  • signed main() {
        int x1 = 0, y1 = 0, x2 = 100, y2 = 100;
    
        // 书上引入了 "策略模式+简单工厂"的结合模式(不需要工厂类)
        // 如果调用方是界面类,那么 算法和界面 就解耦了
        AlgoContext context(edgeCount);
        double dist = context.getResult(x1, y1, x2, y2);
    }
    
posted @ 2021-06-13 21:57  马角的逆袭  阅读(40)  评论(0编辑  收藏  举报