镇江网站建设zjmfkj,万网域名注册后怎么样做网站,西安wordpress开发,引导式网站策略模式 策略模式主要组成部分例一#xff1a;逐步重构并引入策略模式第一步#xff1a;初始实现第二步#xff1a;提取共性并实现策略接口第三步#xff1a;实现具体策略类第四步#xff1a;实现上下文类策略模式 UML 图策略模式的 UML 图解析 例二#xff1a;逐步重构… 策略模式 策略模式主要组成部分例一逐步重构并引入策略模式第一步初始实现第二步提取共性并实现策略接口第三步实现具体策略类第四步实现上下文类策略模式 UML 图策略模式的 UML 图解析 例二逐步重构并引入策略模式第一步初始实现第二步提取共性并实现策略接口第三步实现具体策略类第四步实现上下文类第五步更新主函数 策略模式 UML 图策略模式的 UML 图解析 策略模式优缺点策略模式适用场景例一的完整代码例二的完整代码 策略模式
策略模式是一种行为设计模式它定义了一系列算法将每一个算法封装起来并使它们可以互换。策略模式让算法的变化独立于使用算法的客户。
引入策略“设计模式的定义定义一些列算法类策略类将每个算法封装起来让他们可以互相替换。换句话说策略模式通常把一系列算法封装到一系列具体策略类中作为抽象策略类的字类然后根据实际需要适用这些字类。
主要组成部分 策略接口 (Strategy)定义一个统一的接口声明所有支持的算法策略的方法。客户端通过这个接口调用具体策略。 具体策略类 (Concrete Strategy)实现策略接口定义具体的算法或行为。每个具体策略类实现不同的算法。 上下文类 (Context)持有对策略接口的引用负责调用具体策略的方法。上下文类可以在运行时动态地切换策略。
例一逐步重构并引入策略模式
假设我们需要实现不同的排序算法如冒泡排序和快速排序。最初的实现可能是重复的代码。逐步重构的过程如下
第一步初始实现
为每种排序算法编写独立的处理逻辑
#include iostream
#include vectorvoid bubbleSort(std::vectorint arr) {for (size_t i 0; i arr.size() - 1; i) {for (size_t j 0; j arr.size() - i - 1; j) {if (arr[j] arr[j 1]) {std::swap(arr[j], arr[j 1]);}}}
}void quickSort(std::vectorint arr, int low, int high) {if (low high) {int pivot arr[high];int i low - 1;for (int j low; j high; j) {if (arr[j] pivot) {i;std::swap(arr[i], arr[j]);}}std::swap(arr[i 1], arr[high]);quickSort(arr, low, i);quickSort(arr, i 2, high);}
}int main() {std::vectorint data {5, 3, 8, 6, 2};bubbleSort(data);// 或者使用 quickSort(data, 0, data.size() - 1);return 0;
}第二步提取共性并实现策略接口
识别出排序的共性步骤并创建一个策略接口 SortStrategy定义排序方法
class SortStrategy {
public:virtual void sort(std::vectorint arr) 0; // 策略接口
};第三步实现具体策略类
为每种排序算法实现具体策略类重写排序方法
class BubbleSort : public SortStrategy {
public:void sort(std::vectorint arr) override {for (size_t i 0; i arr.size() - 1; i) {for (size_t j 0; j arr.size() - i - 1; j) {if (arr[j] arr[j 1]) {std::swap(arr[j], arr[j 1]);}}}}
};class QuickSort : public SortStrategy {
public:void sort(std::vectorint arr) override {quickSort(arr, 0, arr.size() - 1);}private:void quickSort(std::vectorint arr, int low, int high) {if (low high) {int pivot arr[high];int i low - 1;for (int j low; j high; j) {if (arr[j] pivot) {i;std::swap(arr[i], arr[j]);}}std::swap(arr[i 1], arr[high]);quickSort(arr, low, i);quickSort(arr, i 2, high);}}
};第四步实现上下文类
创建一个上下文类 Sorter用于使用策略
class Sorter {
private:SortStrategy* strategy;public:Sorter(SortStrategy* strategy) : strategy(strategy) {}void setStrategy(SortStrategy* strategy) {this-strategy strategy;}void sort(std::vectorint arr) {strategy-sort(arr);}
};策略模式 UML 图 策略模式的 UML 图解析 上下文类 (Context) Sorter 类它是上下文类负责使用策略并持有策略的引用。Sorter 类通过 setStrategy 方法设置具体的排序策略并通过 sort 方法调用该策略进行排序。 抽象策略类 (Strategy) SortStrategy 类这是策略接口定义了一个公共方法 sort该方法由具体策略类实现。它确保所有具体策略类都有一致的接口。 具体策略类 (Concrete Strategy) BubbleSort 类实现了 SortStrategy 接口提供了冒泡排序的具体实现。QuickSort 类实现了 SortStrategy 接口提供了快速排序的具体实现。
例二逐步重构并引入策略模式
第一步初始实现
首先从一个简单的实现开始其中战斗者类直接实现道具使用逻辑。
#include iostream
using namespace std;class Fighter {
public:Fighter(int life) : m_life(life) {}void UseBXD() { // 使用补血丹m_life 200;cout 使用补血丹生命值增加200。 endl;}void UseDHD() { // 使用大还丹m_life 300;cout 使用大还丹生命值增加300。 endl;}void UseSHD() { // 使用守护丹m_life 500;cout 使用守护丹生命值增加500。 endl;}int GetLife() {return m_life;}private:int m_life;
};int main() {Fighter warrior(1000);cout 初始生命值 warrior.GetLife() endl;warrior.UseDHD();cout 当前生命值 warrior.GetLife() endl;warrior.UseBXD();cout 当前生命值 warrior.GetLife() endl;warrior.UseSHD();cout 当前生命值 warrior.GetLife() endl;return 0;
}第二步提取共性并实现策略接口
在该实现中Fighter 类包含所有道具使用的逻辑。可以提取出道具使用的共性定义一个道具策略接口。
class ItemStrategy {
public:virtual void UseItem(Fighter* fighter) 0;virtual ~ItemStrategy() {}
};第三步实现具体策略类
为每种道具创建具体的策略类实现 ItemStrategy 接口。
补血丹策略类
class ItemStrategy_BXD : public ItemStrategy {
public:void UseItem(Fighter* mainobj) override {mainobj-SetLife(mainobj-GetLife() 200); // 补充200点生命值}
};大还丹策略类
class ItemStrategy_DHD : public ItemStrategy {
public:void UseItem(Fighter* mainobj) override {mainobj-SetLife(mainobj-GetLife() 300); // 补充300点生命值}
};守护丹策略类
class ItemStrategy_SHD : public ItemStrategy {
public:void UseItem(Fighter* mainobj) override {mainobj-SetLife(mainobj-GetLife() 500); // 补充500点生命值}
};第四步实现上下文类
在 Fighter 类中添加设置道具策略的方法并移除具体的道具使用逻辑并定义战斗者的子类可以不需要字类。
class Fighter {
public:Fighter(int life) : m_life(life), itemStrategy(nullptr) {}void SetItemStrategy(ItemStrategy* strategy) {itemStrategy strategy;}void UseItem() {if (itemStrategy) {itemStrategy-UseItem(this);}}int GetLife() {return m_life;}void SetLife(int life) {m_life life;}private:int m_life;ItemStrategy* itemStrategy;
};
class F_Warrior : public Fighter {
public:F_Warrior(int life, int magic, int attack) : Fighter(life, magic, attack) {}// 其他战士特有的方法
};class F_Mage : public Fighter {
public:F_Mage(int life, int magic, int attack) : Fighter(life, magic, attack) {}// 其他法师特有的方法
};第五步更新主函数
更新主函数以使用新的策略模式结构。
int main() {Fighter warrior(1000);cout 初始生命值 warrior.GetLife() endl;ItemStrategy* strategy1 new ItemStrategy_DHD();warrior.SetItemStrategy(strategy1);warrior.UseItem();cout 当前生命值 warrior.GetLife() endl;ItemStrategy* strategy2 new ItemStrategy_BXD();warrior.SetItemStrategy(strategy2);warrior.UseItem();cout 当前生命值 warrior.GetLife() endl;ItemStrategy* strategy3 new ItemStrategy_SHD();warrior.SetItemStrategy(strategy3);warrior.UseItem();cout 当前生命值 warrior.GetLife() endl;delete strategy1;delete strategy2;delete strategy3;return 0;
}策略模式 UML 图 策略模式的 UML 图解析
Context(环境类)也叫上下文类是使用算法的角色该类中维持着一个对抽象策略类的指针或引用。这里指Fighter类。Stategy(抽象策略类)定义所支持的算法的公共接口是所有策略类的父类。这里指 ItemStrategy 类。ConcreteStrategy(具体策略类)抽象策略类的子类实现抽象策略类中声明的接口。这里指ItemStrategy_BXD、ItemStrategy_DHD、ItemStrategy_SHD类。
策略模式优缺点
优点 灵活性可以在运行时选择不同的策略增加了程序的灵活性和可扩展性。 开放-关闭原则新的策略可以通过实现策略接口而无需修改现有代码符合开放-关闭原则。 清晰的职责分离将不同的算法封装在不同的类中使得代码更加清晰易于维护。 减少条件语句避免了使用大量的条件语句如 if-else 或 switch使代码结构更加简洁。 易于测试每个策略类可以独立测试便于单元测试和调试。
缺点 类的数量增加每种策略都需要一个新的类可能导致类的数量增加增加了系统的复杂性。 客户端必须了解所有策略客户端需要了解所有可用的策略以便选择合适的策略这可能增加了使用的复杂性。 性能开销在某些情况下频繁地创建和销毁策略对象可能导致性能开销。 不适合简单的算法对于简单的算法使用策略模式可能显得过于复杂增加了不必要的抽象。
策略模式适用场景
多种算法当有多个算法可以选择时策略模式可以将它们封装起来方便切换。避免条件语句当使用大量条件语句来选择算法时可以使用策略模式来简化代码结构。动态选择算法当需要在运行时选择算法时策略模式提供了灵活性。算法复用当多个类需要使用同一算法时可以将算法封装成策略类促进代码复用。
例一的完整代码
以下是完整的实现代码
#include iostream
#include vector// 策略接口
class SortStrategy
{
public:virtual void sort(std::vectorint arr) 0; // 策略接口
};// 具体策略冒泡排序
class BubbleSort : public SortStrategy {
public:void sort(std::vectorint arr) override {for (size_t i 0; i arr.size() - 1; i) {for (size_t j 0; j arr.size() - i - 1; j) {if (arr[j] arr[j 1]) {std::swap(arr[j], arr[j 1]);}}}}
};// 具体策略快速排序
class QuickSort : public SortStrategy {
public:void sort(std::vectorint arr) override {quickSort(arr, 0, arr.size() - 1);}private:void quickSort(std::vectorint arr, int low, int high) {if (low high) {int pivot arr[high];int i low - 1;for (int j low; j high; j) {if (arr[j] pivot) {i;std::swap(arr[i], arr[j]);}}std::swap(arr[i 1], arr[high]);quickSort(arr, low, i);quickSort(arr, i 2, high);}}
};// 上下文类
class Sorter {
private:SortStrategy* strategy;public:Sorter(SortStrategy* strategy) : strategy(strategy) {}void setStrategy(SortStrategy* strategy) {this-strategy strategy;}void sort(std::vectorint arr) {strategy-sort(arr);}
};// 示例用法
int main() {std::vectorint data {5, 3, 8, 6, 2};Sorter sorter(new BubbleSort());sorter.sort(data); // 使用冒泡排序sorter.setStrategy(new QuickSort());sorter.sort(data); // 使用快速排序return 0;
}例二的完整代码
#include iostream
using namespace std;class Fighter; // 类前向声明//道具策略类的父类
class ItemStrategy
{
public:virtual void UseItem(Fighter* mainobj) 0;virtual ~ItemStrategy() {}
};//战斗者父类
class Fighter
{
public:Fighter(int life, int magic, int attack) :m_life(life), m_magic(magic), m_attack(attack) {}virtual ~Fighter() {}public:void SetItemStrategy(ItemStrategy* strategy) //设置道具使用的策略{itemstrategy strategy;}void UseItem() //使用道具吃药{itemstrategy-UseItem(this);}int GetLife() //获取人物生命值{return m_life;}void SetLife(int life) //设置人物生命值{m_life life;}private:ItemStrategy* itemstrategy nullptr; //C11中支持这样初始化protected:int m_life;int m_magic;int m_attack;
};//“战士”类父类为Fighter
class F_Warrior :public Fighter
{
public:F_Warrior(int life, int magic, int attack) :Fighter(life, magic, attack) {}
};//“法师”类父类为Fighter
class F_Mage :public Fighter
{
public:F_Mage(int life, int magic, int attack) :Fighter(life, magic, attack) {}
};//补血丹策略类
class ItemStrategy_BXD : public ItemStrategy
{
public:virtual void UseItem(Fighter* mainobj){mainobj-SetLife(mainobj-GetLife() 200); //补充200点生命值cout 使用补血丹生命值增加200。 endl;}
};//大还丹策略类
class ItemStrategy_DHD : public ItemStrategy
{
public:virtual void UseItem(Fighter* mainobj){mainobj-SetLife(mainobj-GetLife() 300); //补充300点生命值cout 使用大还丹生命值增加300。 endl;}
};//守护丹策略类
class ItemStrategy_SHD : public ItemStrategy
{
public:virtual void UseItem(Fighter* mainobj){mainobj-SetLife(mainobj-GetLife() 500); //补充500点生命值cout 使用守护丹生命值增加500。 endl;}
};int main()
{// 创建战斗者对象Fighter* prole_war new Fighter(1000, 0, 200);// 打印初始生命值cout 初始生命值 prole_war-GetLife() endl;// 使用大还丹ItemStrategy* strategy1 new ItemStrategy_DHD();prole_war-SetItemStrategy(strategy1);prole_war-UseItem();cout 当前生命值 prole_war-GetLife() endl;// 使用补血丹ItemStrategy* strategy2 new ItemStrategy_BXD();prole_war-SetItemStrategy(strategy2);prole_war-UseItem();cout 当前生命值 prole_war-GetLife() endl;// 使用守护丹ItemStrategy* strategy3 new ItemStrategy_SHD();prole_war-SetItemStrategy(strategy3);prole_war-UseItem();cout 当前生命值 prole_war-GetLife() endl;// 释放资源delete strategy1;delete strategy2;delete strategy3;delete prole_war;F_Mage mage(800, 300, 100);cout 法师初始生命值 mage.GetLife() endl;// 可以为法师设置道具策略并使用// ...return 0;
}