模板模式UML
多数情况下,可以将部分逻辑进行抽象,在抽象类中定义好如何使用这些抽象方法,然后抽象方法的具体实现交给其他人实现,或者在以后实现,客户端只需要依赖抽象类,而不需要依耐具体的实现,这就可以使得在业务运行的过程中,我们可以根据业务的变换来实现不同的子类。而且这里仅需要的一步就是继承AbastractClass,重写父类中的primitive方法即可,在客户端中,只需要在配置文件中配置成对应的子类即可。
模版模式的实现
1、模版类
public abstract class AbstractClass {
public abstract void primitiveOperation1();
public abstract void primitiveOperation2();
public void templateMethod(){
//在模版方法中,不一定只是简单的调用这两个方法,当然还可以是更复杂的逻辑
primitiveOperation1();
primitiveOperation2();
}
}
2、在子类中实现模版类中的抽象方法
public class ConcreteClass extends AbstractClass {
@Override
public void primitiveOperation1() {
System.out.println("我是子类中的逻辑1,为父类中的模版方法提供处理方法");
}
@Override
public void primitiveOperation2() {
System.out.println("我是子类中的逻辑2,为父类中的模版方法提供处理方法");
}
}
3、客户端测试类
public class Main {
public static void main(String[] args) {
AbstractClass abstractClass = new ConcreteClass(); //这里可以借用反射来决定具体采用哪个类
abstractClass.templateMethod();
}
}
HibernateTemplate中的模版模式
使用过Spring框架和Hibernate的读者应该会对该类比较熟悉,HibernateTemplate类中采用的亦是模版模式。
1、原HibernateTemplate中的execute部分
public <T> T execute(HibernateCallback<T> action) throws DataAccessException {
return doExecute(action, false, false);
}
protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession)
throws DataAccessException {
//...代码省略
Assert.notNull(action, "Callback object must not be null");
//...代码省略
T result = action.doInHibernate(sessionToExpose);
//...代码省略
}
事实上,这里的doExecute就是模版方法,相当于UML图中templateMethod,然后调用了HibernateCallback中的doInHibernate()方法,而该方法正是要求我们重写的方法,与我们上面介绍的模版模式稍微不同的地方是:不是通过继承HibernateTtemplate类来重写其中的抽象方法,而是通过继承HibernateCallback类来重写其中的抽象方法,只需要在调用的时候将HibernateCallback对象传到doExecute()中即可,然后在doExecute()中调用的是HibernateCallback的doInHibernate()方法。
简单的说,就是将上方UML类图中原有的模版类进行了拆分,一个是模版类,一个是抽象方法类。模版类调用抽象方法类中的方法
接下来笔者模拟HibernateTemplate来实现一个MyHibernateTemplate
1、模版类
package template;
public class MyHibernateTemplate {
public <T> T execute(MyHibernateCallback<T> action){
return this.doExecute(action);
}
public <T> T doExecute(MyHibernateCallback<T> action){
T result = action.doInHibernate();
return result;
}
}
2、将具体的操作抽象成一个接口
package template;
public interface MyHibernateCallback<T>{
public T doInHibernate();
}
3、Java Bean,这里应该从数据库中读取
package template;
public class User {
private Integer id;
private String username;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
4、客户端测试类
package template;
public class Main {
public static void main(String[] args) {
MyHibernateTemplate template = new MyHibernateTemplate();
User u = template.doExecute(new MyHibernateCallback<User>() {
@Override
public User doInHibernate() {
//事实上这个地方应该从数据库中读取,当然这里会用到Hibernate框架从数据库中读取数据
User user = new User();
user.setId(1);
user.setUsername("123");
user.setPassword("abc");
return user;
}
});
System.out.println("id:" + u.getId() + ",username:" + u.getUsername() + ",password:" + u.getPassword());
}
}
输出结果:
id:1,username:123,password:abc