一 引入
问题:如何对一个对象类的操作进行解耦,使他们的执行可以动态地安排。
解决:定义一个统一的命令接口,让具体命令对象类的解耦操作。
二 类图
三 实例
继续考察上一遍博文中,数据库连接的实例,在MySqlImpl类中,有四个方法,但是通常远远不止四个方法,如果全写在这一个类中,类将会变得难以理解和维护,所以将其每个方法变为一个类:
3.1 Command Interface——DBCmd.java
public abstract class DBCmd { Object result; public abstract void excute(); public Object getResult(){ return result; } }
3.2 Concrete Command1——ConnectDB.java
public class ConnectDB extends DBCmd { @Override public void excute() { String url = "jdbc:mysql://127.0.0.1/ARS"; String driver = "com.mysql.jdbc.Driver"; Connection conn = null; try { Class.forName(driver);//指定连接类型 conn = DriverManager.getConnection(url, "root", "root");//获取连接 } catch (Exception e) { e.printStackTrace(); } result=conn; } }
3.3 Concrete Command2——DisconnectDB.java
public class DisconnectDB extends DBCmd { Connection conn=null; public DisconnectDB(Connection conn) { super(); this.conn=conn; } @Override public void excute() { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
3.4 Concrete Command3——GetUser.java
public class GetUser extends DBCmd { int id; public GetUser(int id) { super(); this.id=id; } @Override public void excute() { User user=new User(); ConnectDB connectDB=new ConnectDB(); connectDB.excute(); Connection conn=(Connection)connectDB.getResult(); String sql="select * from User where id=?"; try{ PreparedStatement ps=conn.prepareStatement(sql); ps.setInt(1, id); ResultSet rs=ps.executeQuery(); rs.next(); user.setId(rs.getInt("id")); user.setUserName(rs.getString("userName")); user.setPassword(rs.getString("password")); }catch (Exception e) { e.printStackTrace(); } finally { DisconnectDB disconnectDB=new DisconnectDB(conn); disconnectDB.excute(); } result=user; } }
3.5 Concrete Command3——SaveUser.java
public class SaveUser extends DBCmd { @Override public void excute() { } }
按照上面写就好了,这里就不写了。。
3.6 Client.java
public class Client { public static void main(String args[]){ GetUser getUser=new GetUser(1); getUser.excute(); User user=(User)getUser.getResult(); System.out.println(user.getUserName()); } }
四 总结分析
4.1 适用情况
(1)将请求封装为命令对象,如上例。
(2)应用程序需要添加新的请求或函数,如上例需要添加删除User的函数。
(3)应用程序需要将请求排队并在不同的时间执行它们。
(4)应用程序需要动态改变动作执行顺序。
(5)应用程序需要支持撤销和重做。
(6)系统恢复中,应用程序需要记录更改并重做。备忘录模式也可用。
4.2 优点
(1)封装操作为命令对象,操作能灵活执行。
(2)可采用复合模式组成复合命令。
(3)容易添加新命令。
(4)支持撤销和重做操作。
4.3 缺点
所欲方法都变成一个类里的execute了。。。所以你有n多类要写。。