先看一下: C#设计模式 - 模板方法
一、什么是模板方法模式
所谓模板方法模式,其实很简单,可以从模板的角度考虑,就是一个对模板的应用,就好比老师出试卷,每个人的试卷都是一样的,即都是从老师的原版试卷复印来的,这个原版试卷就是一个模板,可每个人写在试卷上的答案都是不一样的,这就是模板方法模式,是不是很好理解。它的主要用途在于将不变的行为从子类搬到超类,去除了子类中的重复代码。
模板方法模式(TemplateMethod),定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。UML结构图如下:
其中,AbstractClass实现类一个模板方法,定义了算法的骨架,具体子类将重定义PrimitiveOperation以实现一个算法的步骤;而ConcreteClass实现了PrimitiveOperation以完成算法中与特定子类相关的步骤。
1. 抽象模板类
定义一个模板方法来组合PrimitiveOperation1()和PrimitiveOperation2()两个方法形成一个算法,然后让子类重定义这两个方法。
复制代码
1 public abstract class AbstractClass {
2
3 public abstract void PrimitiveOperation1();
4 public abstract void PrimitiveOperation2();
5
6 public void TemplateMethod() {
7 PrimitiveOperation1();
8 PrimitiveOperation2();
9 }
10
11 }
2. 具体模板类
这里定义两个具体模板类,ConcreteClassA及ConcreteClassB来进行测试,继承抽象模板类,实现具体方法。
复制代码
1 public class ConcreteClassA extends AbstractClass {
2
3 @Override
4 public void PrimitiveOperation1() {
5 System.out.println(“具体方法A方法1实现”);
6 }
7
8 @Override
9 public void PrimitiveOperation2() {
10 System.out.println(“具体方法A方法2实现”);
11 }
12
13 }
3. Client客户端
通过调用模板方法来分别得到不同的结果。
1 public class Client {
2
3 public static void main(String[] args) {
4 AbstractClass abstractClass;
5
6 abstractClass = new ConcreteClassA();
7 abstractClass.TemplateMethod();
8
9 abstractClass = new ConcreteClassB();
10 abstractClass.TemplateMethod();
11 }
12
13 }
运行结果如下:
二、模板方法模式的应用
1. 何时使用
有一些通用的方法时
2. 方法
将通用算法抽象出来
3. 优点
封装不变部分,扩展可变部分
提取公共部分代码,便于维护
行为由父类控制,子类实现
4. 缺点
每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大
5. 使用场景
有多个子类共有的方法,且逻辑相同
重要的、复杂的方法,可以考虑作为模板方法
重构时,模板方法模式是一个经常使用到的模式,把相同的代码抽取到父类中,通过钩子函数约束其行为
6. 应用实例
做试卷,大家题目都是一样的,只是答案不同
对于汽车,车从发动到停车的顺序是相同的,不同的是引擎声、鸣笛声等
造房时,地基、走线、水管都一样,只有在建筑后期才有差异
7. 注意事项
为防恶意操作,一般模板方法都加上final关键字
回到正题:C# 调用子类方法时强制调用父类方法
解决方法:改变思路,使用模板方法,把访问修饰符Public改为protected。只能访问父类方法,子类方法无法访问,然后在父类方法中调用子类方法
这种方式除了Parent之外没有人调用AddUserImpl – 调用者只使用AddUser,它只是为了正确的位而委托给具体的子类.
public abstract class Parent
{
public void AddUser()
{
Console.WriteLine("我是Parent里面的AddUser方法中调用AddUserImpl之前");
// Preparation goes here
AddUserImpl();
// Clean-up goes here
Console.WriteLine("我是Parent里面的AddUser方法中调用AddUserImpl之后");
}
protected abstract void AddUserImpl();
}
public class Child:Parent
{
protected override void AddUserImpl()
{
// Do stuff here
Console.WriteLine("我是Child里面的AddUserImpl");
}
}
private void button113_Click(object sender, EventArgs e)
{
Parent parent = new Child();
parent.AddUser();
}