锦囊妙计之策略方法模式的应用
1、策略模式完善模板方法模式处理DAO中的查询方法
?
???? 建议先看模模板方法模式在项目中的应用一节,再与本节对比.
?
????1.1 新建RowMapper接口,定义mapRow(ResultSet rs)方法.
???
public interface RowMapper {public Object mapRow(ResultSet rs) throws SQLException;}??? 1.2把抽象类AbstractDao改成JdbcDaoTemplate类.
???
public class JdbcDaoTemplate { //RowMapper是一个接口类,调用此方法时需传入对应的实现类public Object find(String sql, Object[] args, RowMapper rowMapper) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JdbcUtils.getConnection();ps = conn.prepareStatement(sql);for (int i = 0; i < args.length; i++)ps.setObject(i + 1, args[i]);rs = ps.executeQuery();Object obj = null;if (rs.next()) {obj = rowMapper.mapRow(rs);}return obj;} catch (SQLException e) {throw new DaoException(e.getMessage(), e);} finally {JdbcUtils.free(rs, ps, conn);}}}???1.3 将UserDaoImpl类改成如下 :
??
public class UserDaoImpl {JdbcDaoTemplate template = new JdbcDaoTemplate();public User findUser(String loginName, String password) {String sql = "select id, name, money, birthday from user where name=?";Object[] args = new Object[] { loginName };RowMapper mapper = new UserRowMapper();Object user = this.template.find(sql, args, mapper);return (User) user;} //根据用户id查找对应的用户名public String findUserName(int id) {String sql = "select name from user where id=?";Object[] args = new Object[] { id };//通过匿名内部类实现RowMapper接口 策略二:返回的是一个子符串Object name = this.template.find(sql, args, new RowMapper() {public Object mapRow(ResultSet rs) throws SQLException {return rs.getString("name");}});return (String) name;}}//内部类实现的RowMapper接口 策略一:返回的是一个User实体对象class UserRowMapper implements RowMapper {public Object mapRow(ResultSet rs) throws SQLException {User user = new User();user.setId(rs.getInt("id"));user.setName(rs.getString("name"));user.setMoney(rs.getFloat("money"));user.setBirthday(rs.getDate("birthday"));return user;}}????RowMapper 接口对应的角色是抽象策略,此角色定义了策略类所需的接口.
??? UserRowMapper 对应的是具体策略角色,该角色给出对抽象策略的具体实现.
??? JdbcDaoTemplate 对应的是环境角色,持有一个抽象策略接口的引用.
??? UserDaoImpl?
是使者该策略的角色.
?
2、策略模式结构图:
?
?代码表现如下:
?
?2.1 定义接口
?
/** * 抽象策略(角色):此角色给出所有的具体策略类所需的接口 * @author Administrator * */public interface Strategy {//抽象策略(算法)public String strategyInterface();}?
? 2.2 编写环境角色
??
/** * 环境(角色):持有一个Strategy类的引用 * @author Administrator */public class Context {private Strategy strategy;//通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用public Context(Strategy strategy){//初始化时,传入具体的策略对象this.strategy = strategy;}public String getResult(){return strategy.strategyInterface();}}??2.3编写具体策略角色A
?
/** * 具体策略角色A * @author Administrator * */public class ConcreteStrategyA implements Strategy {public String strategyInterface() {return "算法A的实现";}}???2.4编写具体策略角色B
??
/** * 具体策略角色B * @author Administrator * */public class ConcreteStrategyB implements Strategy {public String strategyInterface() {return "算法B的实现";}}?? 2.5编写使用者:测试类
??
public class StrateryTest {public static void main(String[] args) {Context context = new Context(StrategyFactory.getStrategyA());System.out.println(context.getResult());context = new Context(StrategyFactory.getStrategyB());System.out.println(context.getResult());context = new Context(StrategyFactory.getStrategyC());System.out.println(context.getResult());}}??? 打印结果:
??
算法A的实现算法B的实现算法C的实现
3、策略方法模式的优缺点:
?????优缺: 当业务逻辑存在多个判断语句时,使用该模式可以转移if语句.
???? 缺点: 当if语句很多的时候,就会造成编写很多的具体策略类.
?
?
?
?