可以注销的网站,门源县公司网站建设,免费的网页模板网站,wordpress tag内链接模板方法模式#xff1a;从咖啡和茶到Spring框架#xff0c;掌握设计模式的精髓
《Head First 设计模式》是一本经典的设计模式入门书籍#xff0c;它以轻松幽默的方式讲解了设计模式的核心思想。其中#xff0c;模板方法模式是一个非常简单但非常实用的设计模式#xff…模板方法模式从咖啡和茶到Spring框架掌握设计模式的精髓
《Head First 设计模式》是一本经典的设计模式入门书籍它以轻松幽默的方式讲解了设计模式的核心思想。其中模板方法模式是一个非常简单但非常实用的设计模式它可以帮助我们定义算法的骨架同时将具体实现延迟到子类中。今天我们就通过书中的例子结合代码来深入理解模板方法模式并探讨它在JDK和Spring框架中的应用。 什么是模板方法模式
模板方法模式的定义是 在一个方法中定义一个算法的骨架而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。 简单来说模板方法模式就是将算法的通用部分放在父类中而将可变的部分交给子类去实现。这样既能避免代码重复又能保证算法的结构不被破坏。 从咖啡和茶的故事说起
在《Head First 设计模式》中作者用一个咖啡和茶的例子来讲解模板方法模式。我们来看看咖啡和茶的冲泡过程
咖啡的冲泡过程
把水煮沸用沸水冲泡咖啡把咖啡倒进杯子加糖和牛奶
茶的冲泡过程
把水煮沸用沸水浸泡茶叶把茶倒进杯子加柠檬
我们发现咖啡和茶的冲泡过程非常相似只有第2步和第4步有所不同。那么我们是否可以将这个冲泡过程抽象出来形成一个模板方法呢 用模板方法模式实现咖啡和茶
第一步定义抽象类
我们定义一个抽象类 CaffeineBeverage它包含了一个模板方法 prepareRecipe()这个方法定义了冲泡饮料的算法骨架。然后我们将一些步骤延迟到子类中实现。
abstract class CaffeineBeverage {// 模板方法定义了算法的骨架final void prepareRecipe() {boilWater();brew();pourInCup();addCondiments();}// 具体步骤子类必须实现abstract void brew();abstract void addCondiments();// 通用步骤所有子类共享void boilWater() {System.out.println(Boiling water);}void pourInCup() {System.out.println(Pouring into cup);}
}第二步实现具体子类
接下来我们分别实现 Coffee 和 Tea 类它们继承自 CaffeineBeverage并实现各自的 brew() 和 addCondiments() 方法。
class Coffee extends CaffeineBeverage {Overridevoid brew() {System.out.println(Dripping Coffee through filter);}Overridevoid addCondiments() {System.out.println(Adding Sugar and Milk);}
}class Tea extends CaffeineBeverage {Overridevoid brew() {System.out.println(Steeping the tea);}Overridevoid addCondiments() {System.out.println(Adding Lemon);}
}第三步测试代码
现在我们可以通过调用 prepareRecipe() 方法来冲泡咖啡或茶。
public class CaffeineBeverageTest {public static void main(String[] args) {CaffeineBeverage coffee new Coffee();CaffeineBeverage tea new Tea();System.out.println(Making coffee...);coffee.prepareRecipe();System.out.println(\nMaking tea...);tea.prepareRecipe();}
}运行结果
Making coffee...
Boiling water
Dripping Coffee through filter
Pouring into cup
Adding Sugar and MilkMaking tea...
Boiling water
Steeping the tea
Pouring into cup
Adding Lemon模板方法模式的核心思想
通过上面的例子我们可以总结出模板方法模式的核心思想
定义算法的骨架将算法的通用部分放在父类中形成一个模板方法。延迟实现将算法的可变部分延迟到子类中实现。避免代码重复通过抽象类将通用逻辑提取出来避免子类重复代码。 模板方法模式的优点
代码复用将通用逻辑放在父类中子类只需关注自己的实现。扩展性好新增子类时只需实现可变部分而不需要修改算法的结构。符合开闭原则对扩展开放对修改关闭。 模板方法模式的应用场景
模板方法模式非常适合以下场景
固定流程可变细节例如数据处理流程、工作流引擎等。避免重复代码当多个类有相似的逻辑时可以将通用部分提取到父类中。框架设计框架通常定义流程而将具体实现交给用户。 模板方法模式在JDK中的应用
在JDK中模板方法模式也有广泛的应用。例如java.util.AbstractList 就是一个典型的模板方法模式实现。
AbstractList 是一个抽象类它定义了列表操作的通用逻辑而将具体的操作如 get()、set() 等延迟到子类中实现。
public abstract class AbstractListE extends AbstractCollectionE implements ListE {// 模板方法定义了算法的骨架public boolean add(E e) {add(size(), e);return true;}// 具体步骤子类必须实现abstract public E get(int index);abstract public E set(int index, E element);// 通用步骤所有子类共享public void add(int index, E element) {throw new UnsupportedOperationException();}
}通过这种方式AbstractList 提供了一个通用的列表操作框架而具体的实现如 ArrayList、LinkedList 等可以根据自己的需求进行扩展。 模板方法模式在Spring框架中的应用
在Spring框架中模板方法模式也有广泛的应用。例如JdbcTemplate 就是一个典型的模板方法模式实现。
JdbcTemplate 提供了一个通用的数据库操作框架而将具体的SQL执行逻辑交给用户实现。
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {// 模板方法定义了算法的骨架public T T query(String sql, ResultSetExtractorT rse) throws DataAccessException {return query(sql, new ResultSetExtractorT() {Overridepublic T extractData(ResultSet rs) throws SQLException, DataAccessException {return rse.extractData(rs);}});}// 具体步骤用户必须实现public T T query(String sql, ResultSetExtractorT rse) throws DataAccessException {return execute(sql, new PreparedStatementCallbackT() {Overridepublic T doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {ResultSet rs null;try {rs ps.executeQuery();return rse.extractData(rs);} finally {JdbcUtils.closeResultSet(rs);}}});}
}通过这种方式JdbcTemplate 提供了一个通用的数据库操作框架而用户只需关注自己的SQL执行逻辑。 总结
模板方法模式是设计模式中最简单但最实用的模式之一。它通过定义算法的骨架将可变部分延迟到子类中既保证了代码的复用性又增强了系统的扩展性。
通过《Head First 设计模式》中的咖啡和茶例子我们可以清晰地理解模板方法模式的核心思想并掌握如何在实际开发中应用它。
如果你正在学习设计模式不妨从模板方法模式开始用一杯咖啡和茶的时间掌握设计模式的精髓 互动话题你在实际开发中用过模板方法模式吗欢迎在评论区分享你的经验和心得