建站公司网站模板论坛,哈尔滨建设网工程竣工公示,广州计算机编程培训学校,投稿平台在哪里找【设计模式】 策略模式介绍及C代码实现
背景 在软件构建过程中#xff0c;某些对象使用的算法可能多种多样#xff0c;经常改变#xff0c;如果将这些算法都编码到对象中#xff0c;将会使对象变得异常复杂#xff0c;而且有时候支持不使用的算法也是一个性能负担。 如何…【设计模式】 策略模式介绍及C代码实现
背景 在软件构建过程中某些对象使用的算法可能多种多样经常改变如果将这些算法都编码到对象中将会使对象变得异常复杂而且有时候支持不使用的算法也是一个性能负担。 如何在运行时根据需要透明地更改对象的算法将算法与对象本身解耦从而避免上述问题 我们还是使用这个例子比如你要从北京去上海出差出差的工作是不变的但是每次去使用的交通工具却有不同的方式可能有火车、可能飞机、可能开车。如果写程序实现我们就可以分别将不同的交通工具方式写到不同的类中然后再代码运行时根据不同的交通方式调用不同类的对象从而实现在一套代码中通过运行是的调用兼容不同交通工具方式的出差这个场景。 这种定义一系列可互相替换的算法并且每个算法独立封装然后再运行的时候动态替换的方式就是策略模式。
定义 策略模式Strategy Pattern是一种常用的面向对象设计模式它定义了一系列可互相替换的算法或策略并将每个算法封装成独立的对象使得它们可以在运行时动态地替换。 具体来说策略模式定义了一系列算法每个算法都封装在一个具体的策略类中这些策略类实现了相同的接口或抽象类。在使用算法的时候客户端通过一个上下文对象来调用策略类的方法从而完成算法的执行。这样客户端可以在运行时动态地选择不同的策略类从而实现不同的行为。
策略模式通常由三个角色组成 环境角色Context它是客户端代码所定义的一组接口或抽象类表示一种算法或策略。 抽象策略角色Strategy它是一个抽象类或接口定义了一组算法或策略的接口。 具体策略角色Concrete Strategy它是抽象策略的具体实现类实现了策略角色定义的算法或策略。
应用场景
策略模式主要应用在以下场景
当你想使用对象中各种不同的算法变体 并希望能在运行时切换算法时 可使用策略模式。 策略模式让你能够将对象关联至可以不同方式执行特定子任务的不同子对象 从而以间接方式在运行时更改对象行为。
当你有许多仅在执行某些行为时略有不同的相似类时 可使用策略模式。 策略模式让你能将不同行为抽取到一个独立类层次结构中 并将原始类组合成同一个 从而减少重复代码。
如果算法在上下文的逻辑中不是特别重要 使用该模式能将类的业务逻辑与其算法实现细节隔离开来。 策略模式让你能将各种算法的代码、 内部数据和依赖关系与其他代码隔离开来。 不同客户端可通过一个简单接口执行算法 并能在运行时进行切换。 当类中使用了复杂条件运算符以在同一算法的不同变体中切换时 可使用该模式。 策略模式将所有继承自同样接口的算法抽取到独立类中 因此不再需要条件语句。 原始对象并不实现所有算法的变体 而是将执行工作委派给其中的一个独立算法对象。
具体的应用场景包括 订单价格计算根据不同的促销活动如会员折扣、团购活动、满减优惠等可以使用不同的算法来计算订单的价格。 支付方式选择根据不同的支付方式如信用卡、支付宝、微信支付等可以使用不同的算法来完成支付过程。 排序算法选择根据不同的排序算法如冒泡排序、快速排序、归并排序等可以使用不同的算法来排序。 表单验证根据不同的表单验证规则如必填字段、长度限制、格式要求等可以使用不同的算法来验证表单数据的有效性。 在这些场景中策略模式可以帮助我们将算法或策略的实现与算法或策略的使用分离开来从而实现代码的复用、可维护性和灵活性。
模式结构 实现步骤
策略模式设的主要实现步骤 定义一个策略接口或抽象类该接口或抽象类声明了策略所需的方法具体的策略类将实现这些方法。 定义具体的策略类实现策略接口或抽象类中声明的方法。 定义一个上下文类该类包含一个策略对象的引用用于调用策略对象的方法。上下文类也可以定义一些辅助方法用于支持策略的使用。 在客户端中根据需要创建不同的策略对象并将其传递给上下文对象。 在上下文对象中调用策略对象的方法完成具体的算法或行为。
C语言代码示例 其实设计模式是一种与编程语言无关的设计思想但是其中很重要的思想就是面向对象所以在面向对象的语言比如C、Java中实现起来就非常顺手但因为我本人是C语言出身并且作为主要编程语言的所以就使用了C语言来实现模板方法的设计模式。 在C语言中由于没有面向对象的特性策略模式的实现方式会略有不同。通常可以使用函数指针来模拟接口使用函数指针变量来引用具体的策略函数。下面是一个简单的示例演示了如何使用C语言实现策略模式
#include stdio.h// 1. 定义函数指针类型
typedef void (*Strategy)(int, int);// 2. 定义具体的策略函数
void operation_add(int num1, int num2) {printf(%d %d %d\n, num1, num2, num1 num2);
}void operation_subtract(int num1, int num2) {printf(%d - %d %d\n, num1, num2, num1 - num2);
}void operation_multiply(int num1, int num2) {printf(%d * %d %d\n, num1, num2, num1 * num2);
}// 3. 定义上下文结构体
typedef struct {Strategy strategy;
} Context;// 4. 在客户端中使用策略模式
int main() {Context context;// 使用加法策略context.strategy operation_add;context.strategy(10, 5);// 使用减法策略context.strategy operation_subtract;context.strategy(10, 5);// 使用乘法策略context.strategy operation_multiply;context.strategy(10, 5);return 0;
} 在上面的示例中我们首先定义了一个函数指针类型 Strategy该函数指针类型接受两个整型参数并且没有返回值。接着定义了具体的策略函数 operation_add、operation_subtract 和 operation_multiply这些函数都符合 Strategy 函数指针类型的定义。然后定义了上下文结构体 Context该结构体包含一个函数指针类型的成员变量 strategy。最后在 main 函数中创建一个上下文对象 context并分别将不同的策略函数赋值给 context.strategy 成员变量最终调用 context.strategy 函数指针来执行具体的策略函数。 需要注意的是由于C语言没有面向对象的特性策略模式的实现方式相对于其他编程语言会更加笨拙代码可读性也不太好。如果需要实现更复杂的策略模式建议使用其他面向对象的编程语言来实现。
总结 策略模式为组件提供了一系列可重用的算法从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。并且策略模式提供了用条件判断语句以外的另一种选择消除条件判断语句就是在解耦合。含有许多条件判断语句的代码通常都需要策略模式。如果Strategy对象没有实例变量那么各个上下文可以共享同一个Strategy对象从而节省对象开销。
下面我们从设计原则的角度分析策略模式
开闭原则策略模式可以在不修改原有代码的情况下添加、删除、切换不同的策略因此可以有效地满足开闭原则。代码复用不同的策略可以复用相同的代码减少了代码冗余。单一职责原则将不同的算法封装在不同的策略中实现了单一职责原则。
策略模式的主要优点在于 提高了代码的复用性将算法封装在独立的策略类中可以避免代码重复提高了代码的复用性。 易于扩展和维护由于算法的实现与算法的使用分离开来所以在添加新的算法或修改现有算法时不会影响到其他算法的实现和使用易于扩展和维护。 提高了代码的灵活性在运行时动态地选择不同的策略类可以实现不同的行为提高了代码的灵活性。
总之策略模式是一种简单而有效的设计模式可以帮助我们提高代码的复用性、可维护性和灵活性。