跳至主要內容

模板方法模式

约 756 字

模板方法模式

核心思想

模板方法模式允许在基类中定义一个算法框架,并将一些步骤的具体实现延迟到子类中。

典型用例

数据处理

在处理数据的应用中,通常有一个固定的流程(如读取、解析、处理、输出数据),但是每个步骤的具体实现可能根据数据的不同格式而变化。模板方法可以定义处理流程的骨架,而具体步骤的实现则留给子类。

在这个例子中,抽象的数据处理基类定义了数据处理流程,不同的子类实现了具体的数据处理步骤。因此,当需要添加新的数据格式支持时,只需要添加一个新的子类并实现具体的步骤即可,而无需修改现有代码。

// npm run code src/code/design-pattern/template-method/data-processing.ts

export {};

// 创建一个抽象类,定义数据处理的模板方法,并声明在模板方法中使用的抽象步骤
abstract class DataProcessor {
    // 模板方法
    public processData(): void {
        const data = this.readData();
        const parsedData = this.parseData(data);
        const processedData = this.processDataStep(parsedData);
        this.outputData(processedData);
    }

    // 声明抽象步骤
    protected abstract readData(): string;
    protected abstract parseData(data: string): any;
    protected abstract processDataStep(data: any): any;
    protected abstract outputData(data: any): void;
}

// 为不同数据格式创建具体的子类,实现抽象步骤
class JSONDataProcessor extends DataProcessor {
    protected readData(): string {
        // 读取 JSON 数据
        return '{"name": "John", "age": 30}';
    }

    protected parseData(data: string): any {
        // 解析 JSON 数据
        return JSON.parse(data);
    }

    protected processDataStep(data: any): any {
        // 处理数据
        data.processed = true;
        return data;
    }

    protected outputData(data: any): void {
        // 输出数据
        console.log('JSON Data:', data);
    }
}

class XMLDataProcessor extends DataProcessor {
    protected readData(): string {
        // 读取 XML 数据
        return '<user><name>John</name><age>30</age></user>';
    }

    protected parseData(data: string): any {
        // 解析 XML 数据
        // 实现省略...
        return { name: 'John', age: 30 }; // 示例返回值
    }

    protected processDataStep(data: any): any {
        // 处理数据
        data.processed = true;
        return data;
    }

    protected outputData(data: any): void {
        // 输出数据
        console.log('XML Data:', data);
    }
}

const jsonDataProcessor = new JSONDataProcessor();
jsonDataProcessor.processData(); // 将按照 JSON 数据处理流程执行

const xmlDataProcessor = new XMLDataProcessor();
xmlDataProcessor.processData(); // 将按照 XML 数据处理流程执行

软件构建和测试流程

在自动化构建和测试系统中,每个项目可能有不同的构建和测试步骤,但是整个流程是固定的。通过模板方法,可以定义整个构建和测试的框架,然后让具体项目填充具体的构建和测试步骤。

// npm run code src/code/design-pattern/template-method/build-and-test-process.ts

export {};

abstract class BuildAndTestProcess {
    // 这是模板方法
    public execute(): void {
        this.build();
        this.test();
        this.cleanup();
    }

    // 这些是在子类中可能被覆盖的步骤
    protected abstract build(): void;
    protected abstract test(): void;

    // 这是一个通用方法,可以被覆盖,也可以不被覆盖
    protected cleanup(): void {
        console.log('Cleaning up resources...');
    }
}

// 项目A的具体实现
class ProjectA extends BuildAndTestProcess {
    protected build(): void {
        console.log('Building Project A...');
    }

    protected test(): void {
        console.log('Testing Project A...');
    }
}

// 项目B的具体实现
class ProjectB extends BuildAndTestProcess {
    protected build(): void {
        console.log('Building Project B...');
    }

    protected test(): void {
        console.log('Testing Project B...');
    }

    // 重写cleanup方法
    protected cleanup(): void {
        console.log('Custom cleanup for Project B...');
    }
}

// 使用
const projectA = new ProjectA();
projectA.execute();

const projectB = new ProjectB();
projectB.execute();

用户界面渲染流程

在用户界面渲染流程中,模板方法模式可以有效地用于定义一个固定的渲染流程,同时允许子类自定义每个步骤的具体实现。在这个例子中,可以创建一个抽象的基类,定义用户界面渲染的整体流程(如初始化、布局、绘制等),然后允许不同的UI控件通过继承这个基类并重写特定方法来实现各自的渲染逻辑。

// npm run code src/code/design-pattern/template-method/ui-rendering-process.ts

export {};

abstract class UIComponent {
    // 这是模板方法,定义了UI组件的渲染流程
    public render(): void {
        this.initialize();
        this.layout();
        this.draw();
    }

    // 这些是在子类中可能被覆盖的抽象方法
    protected abstract initialize(): void;
    protected abstract layout(): void;
    protected abstract draw(): void;
}

// Button控件的具体实现
class Button extends UIComponent {
    protected initialize(): void {
        console.log('Initializing Button...');
    }

    protected layout(): void {
        console.log('Laying out Button...');
    }

    protected draw(): void {
        console.log('Drawing Button...');
    }
}

// TextBox控件的具体实现
class TextBox extends UIComponent {
    protected initialize(): void {
        console.log('Initializing TextBox...');
    }

    protected layout(): void {
        console.log('Laying out TextBox...');
    }

    protected draw(): void {
        console.log('Drawing TextBox...');
    }
}

// 使用
const button = new Button();
button.render();

const textBox = new TextBox();
textBox.render();

工作业务流程

模板方法模式适合于实现具有固定步骤但每个步骤根据业务规则有所不同的工作流程。例如:在一个订单处理流程中,其中包括验证订单、处理支付和发货等步骤。这些步骤的顺序是固定的,但每个步骤的具体实现可能会根据不同的业务规则而变化。

// npm run code src/code/design-pattern/template-method/business-process.ts

export {};

// 定义抽象的工作流程类
abstract class WorkflowProcess {
    // 模板方法,定义了工作流程的步骤
    public execute(): void {
        this.validate();
        this.process();
        this.complete();
    }

    // 抽象方法,由子类实现具体的业务逻辑
    protected abstract validate(): void;
    protected abstract process(): void;
    protected abstract complete(): void;
}

// 特定的订单处理流程实现
class OrderProcessing extends WorkflowProcess {
    protected validate(): void {
        console.log('Validating order...');
        // 实现订单验证逻辑
    }

    protected process(): void {
        console.log('Processing payment...');
        // 实现支付处理逻辑
    }

    protected complete(): void {
        console.log('Completing order and shipping...');
        // 实现订单完成和发货逻辑
    }
}

// 特定的审批流程实现
class ApprovalProcess extends WorkflowProcess {
    protected validate(): void {
        console.log('Validating approval request...');
        // 实现审批请求验证逻辑
    }

    protected process(): void {
        console.log('Processing approval...');
        // 实现审批处理逻辑
    }

    protected complete(): void {
        console.log('Completing approval...');
        // 实现审批完成逻辑
    }
}

// 使用
const orderProcess = new OrderProcessing();
orderProcess.execute();

const approvalProcess = new ApprovalProcess();
approvalProcess.execute();

算法骨架

在算法库的上下文中,模板方法模式可以用来定义复杂算法的基本结构或骨架,允许用户或其他开发者根据特定需求实现具体的步骤。例如:在实现一个机器学习算法时,可能会有一个固定的流程:数据预处理、模型训练、结果评估。这个流程的每个步骤都可以根据特定的算法或数据集进行定制。

// npm run code src/code/design-pattern/template-method/algorithm-skeleton.ts

export {};

// 定义抽象的机器学习算法类
abstract class MachineLearningAlgorithm {
    // 模板方法,定义了算法的步骤
    public execute(): void {
        this.preprocess();
        this.train();
        this.evaluate();
    }

    // 抽象方法,由子类实现具体的逻辑
    protected abstract preprocess(): void;
    protected abstract train(): void;
    protected abstract evaluate(): void;
}

// 特定的机器学习算法实现,例如决策树
class DecisionTreeAlgorithm extends MachineLearningAlgorithm {
    protected preprocess(): void {
        console.log('Preprocessing data for Decision Tree...');
        // 实现决策树的数据预处理逻辑
    }

    protected train(): void {
        console.log('Training Decision Tree model...');
        // 实现决策树模型的训练逻辑
    }

    protected evaluate(): void {
        console.log('Evaluating Decision Tree model...');
        // 实现决策树模型的评估逻辑
    }
}

// 使用
const decisionTree = new DecisionTreeAlgorithm();
decisionTree.execute();

上次编辑于: