7.java模板模式与8.策略模式示例

[b]模板方法简介:[/b]
把一些公用的通用的内容抽出来,个性的变动的内容做为参数暴露出来,做为一个模板。在使用时只用传递不同的参数到此模板,便可以得到想要的数据结果,这就是设计模式中得模板方法模式。

下面是使用模板方法来设计dao层的代码示例:

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

/**
* 定义一个抽象的dao父类
*
* @author wb_gaobingyin
*
*/
abstract class BaseDao {
/**
* 这里把查询对象时的公用的地方抽出来了,做为查询单个对象的一个模板,
* 具体的查询将在这个模板上开展,这种处理的方式就叫做模板方法。
* @param sql
* @param args
* @return
*/
public Object getObject(String sql, Object[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
Object obj = null;
try {
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);// 给sql中得参数赋值
}
if (rs.next()) {
obj = this.RowMapperMethod(rs);// 这个方法调用的时总会调用子类中实现的具体方法,进行不同的字段与属性的映射
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放数据库链接对象
}
return obj;
}

public abstract Object RowMapperMethod(ResultSet rs) throws SQLException;
}

class UserDaoImpl extends BaseDao {
/**
* 根据id查询user对象
*
* @return User
*/
public User getUser() {
String sql = "select user_id,user_name,age from uset_tbl where user_id=?";
Object[] args = new Object[] { "abing" };
User user = (User) this.getObject(sql, args);// 在模板的基础上传入参数,获得想要的结果
return user;
}

/**
* 实现基类中的映射方法,不对的实现dao里有不同的装配方式
*/
public Object RowMapperMethod(ResultSet rs) throws SQLException {
User user = new User();
user.setUserId(rs.getString("user_id"));
user.setUserName(rs.getString("user_name"));
user.setAge(rs.getInt("age"));
return user;
}

}

class User {

private String userId;
private String userName;
private int age;

public String getUserId() {
return userId;
}

public void setUserId(String userId) {
this.userId = userId;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}



上面dao的设计基础上,假如我现在有一个新的需求,即根据userId仅仅查询出userName,那该如何处理,如何拓展,显然上面的模板已经不能够满足了,是不是需要再写一个模板呢。想想抽模板的过程,是把不变的部分抽出来,而变的部分sql,args做为参数暴露出,装配参数也是变的,所以是用抽象方法让子类去实现。目前的问题就出在装配上,能不能把装配的过程也做为一个参数传递呢?这里就需要用的策略模式了。
[b]策略模式简介:[/b]
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。(例如FlyBehavior和QuackBehavior) 2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。(例如FlyBehavior和QuackBehavior的具体实现可任意变化或扩充)  
3、 对客户(Duck)隐藏具体策略(算法)的实现细节,彼此完全独立。

下面是使用策略模式在模板方法之上的dao层改进代码:

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

/**
* 定义一个抽象的dao父类
*
* @author abing
*
*/
class BaseDao {
/**
* 在模板方法的基础上,为getObject方法添加了一个RowMapper[策略接口]接口属性,
* 通过调用方构建不同的RowMapper[策略接口]来完成不同的行为
*
* @param sql
* @param args
* @return
*/
public Object getObject(String sql, Object[] args, RowMapper rm) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
Object obj = null;
try {
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);// 给sql中得参数赋值
}
if (rs.next()) {
obj = rm.mapRows(rs);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放数据库链接对象
}
return obj;
}

}

/**
* 定义一个行映射器-[策略接口] 只需要这么一个接口,通过内部类的使用就可以构建不同的方法实现体,来完成不同的事情
*
* @author abing
*
*/
interface RowMapper {
public Object mapRows(ResultSet rs) throws SQLException;
}

class UserDaoImpl extends BaseDao {
/**
* 根据id查询user对象
*
* @return User
*/
public User getUser() {
String sql = "select user_id,user_name,age from uset_tbl where user_id=?";
Object[] args = new Object[] { "abing" };
// 这里使用匿名内部类
User user = (User) this.getObject(sql, args, new RowMapper() {
@Override
public Object mapRows(ResultSet rs) throws SQLException {
// 构建并且返回user对象,这是一种策略
User user = new User();
user.setUserId(rs.getString("user_id"));
user.setUserName(rs.getString("user_name"));
user.setAge(rs.getInt("age"));
return user;

}
});
return user;
}

/**
* 根据id查询userName属性
*
* @return User
*/
public String getUserName() {
String sql = "select user_id,user_name,age from uset_tbl where user_id=?";
Object[] args = new Object[] { "abing" };
// 构建且仅返回userName字符串对象,这也是一种策略
String userName = (String) this.getObject(sql, args, new RowMapper() {
@Override
public Object mapRows(ResultSet rs) throws SQLException {
// TODO Auto-generated method stub
return rs.getString("user_name");
}
});
return userName;
}

}

class User {

private String userId;
private String userName;
private int age;

public String getUserId() {
return userId;
}

public void setUserId(String userId) {
this.userId = userId;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}

你可能感兴趣的:(重构与设计模式)