模板方法(Template Method)模式

介绍模板方法模式的概念及其应用实例,探讨如何通过回调机制解决子类泛滥问题,并给出数据库查询的具体示例。
部署运行你感兴趣的模型镜像

模板方法(Template Method)模式定义:

Define the skeleton of an algorithm in an operation , deferring some steps to subclasses . Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure .

定义一个操作中的一个算法框架,把一些步骤推迟到子类去实现。模板方法模式让子类不需要改变算法结构而重新定义特定的算法步骤。

也就是说:模板方法模式定义了一系列算法步骤,子类可以去实现或覆盖其中某些步骤,但不能改变这些步骤的执行顺序。

下面的代码是模板方法模式的示例代码,类HappyPeople的方法celebrateSpringFestival()是一个模板方法,有3个步骤,其中方法travel()是抽象部分,用于子类实现不同客户化逻辑。

package pattern.part1.chapter2.template;

/**
 * Date: 2009-11-18
 * Time: 0:42:25
 */
public class HappyPeopleTestDrive {
    public static void main(String[] args) {
        HappyPeople passengerByAir = new PassengerByAir();
        HappyPeople passengerByCoach = new PassengerByCoach();
        HappyPeople passengerByTrain = new PassengerByTrain();

        System.out.println("Let's Go Home For A Grand Family Reunion...\n");

        System.out.println("Tom is going home:");
        passengerByAir.celebrateSpringFestival();

        System.out.println("\nRoss is going home:");
        passengerByCoach.celebrateSpringFestival();

        System.out.println("\nCatherine is going home:");
        passengerByTrain.celebrateSpringFestival();
    }
}

package pattern.part1.chapter2.template;


public abstract class HappyPeople {
    public void celebrateSpringFestival() {
        subscribeTicket();
        travel();
        celebrate();
    }

    protected final void subscribeTicket() {
        //Buying ticket...
        System.out.println("Buying ticket...");
    }

    protected abstract void travel();

    protected final void celebrate() {
        //Celebrating Chinese New Year...
        System.out.println("Happy Chinese New Year!");
    }
}

package pattern.part1.chapter2.template;

/**
 * Date: 2009-11-18
 * Time: 0:23:43
 */
public class PassengerByAir extends HappyPeople {
    @Override
    protected void travel() {
        //Traveling by Air...
        System.out.println("Travelling by Air...");
    }
}

package pattern.part1.chapter2.template;

/**
 * Date: 2009-11-18
 * Time: 0:22:16
 */
public class PassengerByCoach extends HappyPeople {
    @Override
    protected void travel() {
        //Travel by Coach...
        System.out.println("Travelling by Coach...");
    }
}

package pattern.part1.chapter2.template;

/**
 * Date: 2009-11-18
 * Time: 0:20:05
 */
public class PassengerByTrain extends HappyPeople {
    @Override
    protected void travel() {
        //Travel by Train...
        System.out.println("Travelling by Train...");
    }
}

模版方法模式可以解决某些场景中的代码冗余问题,但也可能引入类的泛滥问题。使用回调可以避免类的泛滥。

回调表示一段可执行逻辑的引用(或者指针),我们把该引用(或者指针)传递到另外一段逻辑(方法)里供这段逻辑适时调用。

比如针对以下需求:查询数据库的记录。

1.得到数据库连接Connection对象;

2.创建Statement对象并执行相关的查询语句;

3.处理查询出来的结果,并在整个执行过程中处理异常。

整个过程中发生变化的主要是第3步,适合用模板模式来处理这个问题,但由于各种各样的查询太多,导致我们需要创建很多的子类来处理这些查询结果,会引起子类的泛滥。因此,我们可以使用回调(Callback)来解决这个问题。

package com.chapter2.callback;
import static org.junit.Assert.assertEquals;

import java.sql.ResultSet;

import org.junit.Test;
public class TemplateTestDrive {
	@Test
	public void testTemplate(){
		boolean called = new SimpleJDBCTemplate()
		.query("Select * from DB", 
				new ResultSetHandler<Boolean>(){
					@Override
					public Boolean handle(ResultSet rs) {
						return true;
					}
			});
		assertEquals(true,called);
	}

}

package com.chapter2.callback;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class SimpleJDBCTemplate {
	public <T> T query(String queryString,ResultSetHandler<T> rsHandler){
		Connection connection = null;
		PreparedStatement statement=null;
		ResultSet rs=null;
		try {
			connection = ConnectionUtils.getConnection();
			statement = connection.prepareStatement(queryString);
			rs = statement.executeQuery();
			return rsHandler.handle(rs);
		} catch (SQLException ex) {
			closeStatement(statement);
			statement=null;
			releaseConnection(connection);
			connection=null;
			throw new RuntimeException("a sql exception occured",ex);
		}finally{
			closeStatement(statement);
			releaseConnection(connection);
		}
		
	}
	
	private void releaseConnection(Connection conn){
		if(conn!=null){
			try {
				conn.close();//close the connection or put it back  to the connection pool
			} catch (SQLException e) {
				//todo handle SQLException
			} catch (Throwable ex) {
                //todo handle other exception
            }
		}
	}
	
	private void closeStatement(PreparedStatement statement){
		if(statement!=null){
			try {
				statement.close();
			} catch (SQLException e) {
				//todo handle SQLException
			} catch (Throwable ex) {
                //todo handle other exception
            }
		}
	}
}

package com.chapter2.callback;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class ConnectionUtils {
	public static Connection getConnection(){
		Connection connection = createMock(Connection.class);
		PreparedStatement statement = createMock(PreparedStatement.class);
		try {
			expect(connection.prepareStatement((String)anyObject())).andReturn(statement);
			expect(statement.executeQuery()).andReturn(null);
			replay(connection);
			replay(statement);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return connection;
	}

}
package com.chapter2.callback;

import java.sql.ResultSet;

public interface ResultSetHandler<T> {
	public T handle(ResultSet rs);
}

注:本文大部分内容点来自刘济华的《漫谈设计模式》

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

模板方法设计模式Template Method Design Pattern)是一种行为型设计模式,用于定义算法的骨架,同时允许子类在不改变算法结构的情况下重新定义某些步骤。该模式通过将不变的部分封装在抽象基类中,并将可变部分延迟到子类中实现,从而实现了代码复用和扩展性。 ### UML 类图 以下是 `Template Method` 模式的典型 UML 类图结构: ``` +---------------------+ | AbstractClass | +---------------------+ | + templateMethod(): void | | # primitiveOperation1(): void | | # primitiveOperation2(): void | +---------------------+ ▲ | +---------------------+ | ConcreteClass | +---------------------+ | # primitiveOperation1(): void | | # primitiveOperation2(): void | +---------------------+ ``` - **AbstractClass**:定义了一个模板方法 `templateMethod()`,其中包含算法的整体流程,并调用若干原语操作(primitive operations)。这些原语操作通常被声明为受保护的抽象方法,由子类具体实现。 - **ConcreteClass**:继承自 `AbstractClass`,并实现了具体的原语操作。 ### 示例代码 以下是一个使用模板方法模式Java 实现示例,展示了如何定义一个算法框架并在子类中实现具体步骤: ```java // 抽象类,定义模板方法和原语操作 abstract class Game { abstract void initialize(); abstract void startPlay(); abstract void endPlay(); // 模板方法,定义游戏流程 public final void play() { initialize(); // 初始化游戏 startPlay(); // 开始游戏 endPlay(); // 结束游戏 } } // 具体类 - 足球游戏 class FootballGame extends Game { @Override void initialize() { System.out.println("Football Game Initialized! Start playing."); } @Override void startPlay() { System.out.println("Football Game Started. Enjoy the game!"); } @Override void endPlay() { System.out.println("Football Game Finished!"); } } // 测试类 public class TemplateMethodPatternDemo { public static void main(String[] args) { Game game = new FootballGame(); game.play(); // 调用模板方法 } } ``` 运行结果: ``` Football Game Initialized! Start playing. Football Game Started. Enjoy the game! Football Game Finished! ``` 上述代码展示了模板方法模式的核心思想:父类控制整体流程,子类实现具体细节[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值