代码实现:
#include <stdio.h>// 定义抽象基类
typedef struct {void (*step1)(void);void (*step2)(void);void (*step3)(void);
} AbstractClass;// 具体实现类1
void concreteStep1() {printf("Concrete Step 1\n");
}void concreteStep2() {printf("Concrete Step 2\n");
}void concreteStep3() {printf("Concrete Step 3\n");
}// 具体实现类2
void anotherConcreteStep1() {printf("Another Concrete Step 1\n");
}void anotherConcreteStep2() {printf("Another Concrete Step 2\n");
}void anotherConcreteStep3() {printf("Another Concrete Step 3\n");
}// 模板方法
void templateMethod(AbstractClass* obj) {obj->step1();obj->step2();obj->step3();
}int main() {// 创建具体实现类1的对象并调用模板方法AbstractClass obj1 = {concreteStep1, concreteStep2, concreteStep3};templateMethod(&obj1);// 创建具体实现类2的对象并调用模板方法AbstractClass obj2 = {anotherConcreteStep1, anotherConcreteStep2, anotherConcreteStep3};templateMethod(&obj2);return 0;
}
在上面的示例代码中,首先定义了一个抽象基类AbstractClass
,其中包含了三个函数指针,对应模板方法中的三个步骤。然后定义了具体实现类concreteStep1
、concreteStep2
和concreteStep3
,以及另一个具体实现类anotherConcreteStep1
、anotherConcreteStep2
和anotherConcreteStep3
,它们分别实现了抽象基类中的三个步骤。
接下来定义了模板方法templateMethod
,它接收一个抽象基类对象作为参数,并依次调用对象的三个函数指针,完成算法的骨架部分。最后,在main
函数中创建了两个不同的具体实现类的对象,并调用模板方法进行测试。
模板方法模式将算法的骨架和具体步骤的实现进行了解耦,通过在抽象基类中定义模板方法,并使用函数指针回调具体实现类的函数来实现多态性,可以灵活地扩展和定制算法的具体步骤。
模板方法模式是一种典型的行为型设计模式,其主要优缺点如下:
优点:
- 封装不变部分:将算法的骨架和具体实现分离,把不变的部分封装到父类中,可以提高代码复用性和可维护性。
- 提高可扩展性:子类可以通过重写父类的钩子方法,来改变算法的某些步骤,从而增强了模板方法的灵活性和可扩展性。
- 便于维护:模板方法模式使得算法的各个步骤都有明确的定义,易于调试和维护。
缺点:
- 增加了类的数量:为了实现模板方法模式,需要定义抽象类或接口,以及具体实现类,会增加类的数量和层次。
- 限制了继承的使用:由于模板方法模式采用了父类调用子类的方式,因此对子类的继承有一定的限制,子类必须遵循父类定义的算法骨架。
- 不适合复杂算法:如果算法的步骤太多或者太复杂,可能会导致模板方法变得过于庞大和复杂,难以维护和扩展。
适用场景:
- 算法的骨架已经确定,但是某些步骤的具体实现可能不同。
- 需要封装一些复杂的流程,使得屏蔽细节,提高代码复用性,以及便于维护。
- 具有多个子类共同实现某个方法,并且这些子类中的部分步骤相同,部分步骤不同。