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
的子类Dijkstra
和Spfa
- 可以分别编写测试类
DijkstraTest
和SpfaTest
,简化了测试
#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); }