在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。
我觉得设计模式是 十分重要的但设计模式这个东西我学一次忘一次关键是没有一个好例子好场景让我们去体会设计模式的好处。这里我发现了一个策略模式的好例子。
系统中所有实体对象都涉及到基本的CRUD操作所有实体的CUD操作代码基本相同,仅仅发送给数据库的SQL语句不同而已,因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的SQL语句。实体的R操作,除SQL语句不同之外,根据操作的实体不同,对ResultSet的映射也各不相同,因此可义一个query方法,除以参数形式接收变化的SQL语句外,可以使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中。
从数据库查询数据得结果可以是一个对象也可以是一个集合有许许多多的方式可以封装数。我们把这些定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
首先先建一个接口,处理结果集ResultSet。
public interface ResultSetHandler {
public Object handler(ResultSet rs);
}
元数据的知识
ResultSet. getMetaData() 获得代表ResultSet对象元数据的ResultSetMetaData对象。
ResultSetMetaData对象的常用方法:- getColumnCount() 返回resultset对象的列数
- getColumnName(int column) 获得指定列的名称
- getColumnTypeName(int column)获得指定列的类型
public class BeanHandler implements ResultSetHandler {
private Class<?> clazz;
public BeanHandler(Class<?> clazz) {
super();
this.clazz=clazz;
}
@Override
public Object handler(ResultSet rs) {
try {
if(!rs.next())
{
return null;
}
Object bean = clazz.newInstance();
ResultSetMetaData metadata = (ResultSetMetaData) rs.getMetaData();//获得元数据对象
int columncount = metadata.getColumnCount();//获取数据列数
for(int i=0;i<columncount;i++)//用户根据实际业务从数据库中查询了一条数据
{
String columnname=metadata.getColumnName(i+1);//列名
Object columnData=rs.getObject(i+1);//对应数据
Field f = clazz.getDeclaredField("columnname");//根据列名通过反射查找对应的属性名
f.setAccessible(true);//设置可以访问private属性
f.set(bean, columnData);//设置属性值
}
return bean;
} catch (Exception e) {
}
return null;
}
}
先实现一个将resultset中数据处理成一个对象的集合的实现类 返回list的ResultSetHandler与返回bean的不同就是一个返回多条数据需要创建多个对象封装每条数据然后添加到list中一个只要返回一条数据封装一个对象然后返回
public class ListBeanHandler implements ResultSetHandler {
private Class clazz;
@Override
public Object handler(ResultSet rs) {
try {
if(!rs.next())
{
return null;
}
List<Object> list = new ArrayList<Object>();
while(rs.next())
{
Object bean = clazz.newInstance();
ResultSetMetaData rsmd=(ResultSetMetaData) rs.getMetaData();//获得元数据对象
int columnnum=rsmd.getColumnCount();//获取数据列数
for(int i=0;i<columnnum;i++)
{
String name=rsmd.getColumnName(i+1);//列名
String data=(String) rs.getObject(i+1);//对应数据
java.lang.reflect.Field f =clazz.getDeclaredField(name);//根据列名通过反射查找对应的属性名
f.setAccessible(true);//设置可以访问private属性
f.set(bean, data);//设置属性值
}
list.add(bean);
}
return list.size()>0?list:null;
} catch (Exception e) {
throw new RuntimeException();
}
}
}
定义一个jdbc工具类
public class JdbcUtils {
private static String driver;
private static String url;
private static String username;
private static String password;
static
{
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties p = new Properties();
try {
p.load(in);
driver=p.getProperty("driver");
url=p.getProperty("url");
username=p.getProperty("username");
password=p.getProperty("password");
Class.forName(driver);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException
{
return (Connection) DriverManager.getConnection(url,username,password);
}
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
//关闭存储查询结果的ResultSet对象
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
//关闭负责执行SQL命令的Statement对象
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(conn!=null){
try{
//关闭Connection数据库连接对象
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
public static Object query(String sql,Object params[],ResultSetHandler rsh) throws SQLException
{
Connection conn=getConnection();
PreparedStatement ps = (PreparedStatement) conn.prepareStatement(sql);
for(int i=0;i<params.length;i++)
{
ps.setObject(i+1, params);
}
ResultSet rs = (ResultSet) ps.executeQuery();
return rsh.handler(rs);
}
}
使用
public Account find(int id) throws SQLException
{
String sql = "select * from account where id=?";
Object params[] = {id};
//通过传入一个ResultsetHandler用户可以根据业务灵活的选择数据得返回类型
return (Account) JdbcUtils.query(sql, params, new BeanHandler(Account.class));
}
public List<Account> getAll() throws SQLException
{
String sql = "select * from account";
Object params[] = {};
//通过传入一个ResultsetHandler用户可以根据业务灵活的选择数据得返回类型
return (List<Account>) JdbcUtils.query(sql, params,new BeanListHandler(Account.class));
}
这就实现了将返回结果算法封装成一个一个的类,任意地替换。
参考资料: