一.模板模式介绍与使用场景
模板模式(Template Pattern)是一种行为设计模式,它定义了一个操作中的算法骨架,将一些步骤延迟到子类中实现。模板模式使得子类可以在不改变算法结构的情况下重新定义算法的某些步骤。
在模板模式中,通常有两个主要角色:抽象模板(Abstract Template)和具体模板(Concrete Template)。抽象模板定义了算法的骨架,包含了一些抽象方法和具体方法,而具体模板实现了抽象模板中定义的抽象方法。
当存在多个相关的算法或行为,并且需要在运行时动态选择其中之一时,策略模式非常有用。它允许将算法封装在独立的策略类中,使得它们可以互相替换,而不影响客户端代码。
使用策略模式可以消除大量的条件语句。
当存在许多条件语句来根据不同的情况执行不同的行为时,将每个条件对应的行为抽象为独立的策略类,可以使代码更清晰、易于维护,并提高可读性。
策略模式可以提高算法的独立性。将每个算法封装在策略类中,使得每个算法可以独立于其他算法进行修改和演化。这样可以保持代码的灵活性和可维护性。
当需要在系统中添加新的算法或行为时,策略模式提供了一种方便的扩展机制。通过定义新的策略类,可以方便地添加新的算法或行为,而不需要修改现有的代码。
策略模式可以避免类之间的紧耦合关系和继承层次结构的复杂性。通过将算法抽象为独立的策略类,而不是通过继承来实现不同的行为,可以降低类之间的耦合度,使代码更加灵活和可扩展。
二.模板模式实现
例如我们实现一个使用模板方法煮茶和咖啡的例子
// 抽象模板类 abstract class BeverageTemplate { // 模板方法,定义算法的骨架 public final void prepareBeverage() { boilWater(); brew(); pourInCup(); addCondiments(); System.out.println("饮料制作完成!"); } // 具体方法 private void boilWater() { System.out.println("加开水"); } // 抽象方法,由子类实现 protected abstract void brew(); // 具体方法 private void pourInCup() { System.out.println("把饮料倒杯子里"); } // 抽象方法,由子类实现 protected abstract void addCondiments(); } // 具体模板类 - 咖啡 class Coffee extends BeverageTemplate { protected void brew() { System.out.println("冲泡咖啡"); } protected void addCondiments() { System.out.println("加糖、加奶"); } } // 具体模板类 - 茶 class Tea extends BeverageTemplate { protected void brew() { System.out.println("泡茶"); } protected void addCondiments() { System.out.println("加柠檬"); } } // 使用示例 public class Main { public static void main(String[] args) { System.out.println("做杯咖啡..."); BeverageTemplate coffee = new Coffee(); coffee.prepareBeverage(); System.out.println("做杯茶..."); BeverageTemplate tea = new Tea(); tea.prepareBeverage(); } }
上述示例中,我们定义了一个抽象模板类 BeverageTemplate,它包含了 prepareBeverage 方法作为算法的骨架,以及其他具体方法。prepareBeverage 方法中的具体步骤被定义为模板方法,不能被子类修改。然而,brew 和 addCondiments 方法是抽象的,需要由具体子类来实现。
然后,我们创建了两个具体模板类 Coffee(咖啡)和 Tea(茶),它们继承了抽象模板类,并实现了 brew 和 addCondiments 方法。
在 Main 类的 main 方法中,我们演示了使用模板模式来准备咖啡和茶的过程。首先,我们创建了一个咖啡对象并调用 prepareBeverage 方法,该方法按照定义好的算法骨架执行咖啡的制作过程。然后,我们创建了一个茶对象并执行相同的步骤。
通过使用模板模式,我们将算法的通用部分封装在抽象模板中,而具体的实现细节由子类来完成。这样,我们可以在不改变算法结构的情况下,通过扩展具体模板类来改变算法中的某些步骤。
下面我们用一个电商系统中发布商品的场景,来写一个模板模式的demo
// 抽象模板类 - 商品发布 abstract class ProductPublishTemplate { // 模板方法,定义商品发布的流程 public final void publishProduct() { validateProduct(); prepareProduct(); uploadImages(); publishListing(); System.out.println("Product has been published!"); } // 具体方法 - 验证商品信息 private void validateProduct() { System.out.println("Validating product information"); } // 抽象方法 - 准备商品 protected abstract void prepareProduct(); // 具体方法 - 上传商品图片 private void uploadImages() { System.out.println("Uploading product images"); } // 抽象方法 - 发布商品 protected abstract void publishListing(); } // 具体模板类 - 电子产品发布 class ElectronicsProductPublish extends ProductPublishTemplate { protected void prepareProduct() { System.out.println("Preparing electronics product"); // 具体的准备电子产品的逻辑 } protected void publishListing() { System.out.println("Publishing electronics product listing"); // 具体的发布电子产品的逻辑 } } // 具体模板类 - 服装产品发布 class ApparelProductPublish extends ProductPublishTemplate { protected void prepareProduct() { System.out.println("Preparing apparel product"); // 具体的准备服装产品的逻辑 } protected void publishListing() { System.out.println("Publishing apparel product listing"); // 具体的发布服装产品的逻辑 } } // 使用示例 public class Main { public static void main(String[] args) { System.out.println("Publishing electronics product..."); ProductPublishTemplate electronicsProduct = new ElectronicsProductPublish(); electronicsProduct.publishProduct(); System.out.println("Publishing apparel product..."); ProductPublishTemplate apparelProduct = new ApparelProductPublish(); apparelProduct.publishProduct(); } }
我们定义了一个抽象模板类 ProductPublishTemplate,它包含了 publishProduct 方法作为商品发布的流程骨架,以及其他具体方法。publishProduct 方法中的具体步骤被定义为模板方法,不能被子类修改。然而,prepareProduct 和 publishListing 方法是抽象的,需要由具体子类来实现。
然后,我们创建了两个具体模板类 ElectronicsProductPublish(电子产品发布)和 ApparelProductPublish(服装产品发布),它们继承了抽象模板类,并实现了 prepareProduct 和 publishListing 方法。
在 Main 类的 main 方法中,我们演示了使用模板模式来发布电子产品和服装产品的过程。首先,我们创建了一个电子产品对象并调用 publishProduct 方法,该方法按照定义好的商品发布流程执行电子产品的发布过程。然后,我们创建了一个服装产品对象并执行相同的步骤。
由于我们定义的prepareProduct(准备商品方法)和publishListing(发布商品方法)是抽象方法,当我们需要改变某个类别商品的发布逻辑时,可以直接修改这两个方法,不需要判断商品是否属于这个类别。
这样,我们可以在不改变商品发布流程的情况下,通过扩展具体模板类来改变商品发布的某些步骤。