请求发送者与接收者解耦—命令模式(二)

3 完整解决方案

       为了降低功能键与功能处理类之间的耦合度,让用户可以自定义每一个功能键的功能,Sunny软件公司开发人员使用命令模式来设计“自定义功能键”模块,其核心结构如图4所示:

请求发送者与接收者解耦—命令模式(二)

 

4 自定义功能键核心结构图

       在图4中,FBSettingWindow是“功能键设置”界面类,FunctionButton充当请求调用者,Command充当抽象命令类,MinimizeCommandHelpCommand充当具体命令类,WindowHanlderHelpHandler充当请求接收者。完整代码如下所示:

  1. import java.util.*;  
  2.   
  3. //功能键设置窗口类  
  4. class FBSettingWindow  
  5.     private String title; //窗口标题  
  6.     //定义一个ArrayList来存储所有功能键  
  7.     private ArrayList functionButtons new ArrayList();  
  8.       
  9.     public FBSettingWindow(String title)  
  10.         this.title title;  
  11.      
  12.       
  13.     public void setTitle(String title)  
  14.         this.title title;  
  15.      
  16.       
  17.     public String getTitle()  
  18.         return this.title;  
  19.      
  20.       
  21.     public void addFunctionButton(FunctionButton fb)  
  22.         functionButtons.add(fb);  
  23.      
  24.       
  25.     public void removeFunctionButton(FunctionButton fb)  
  26.         functionButtons.remove(fb);  
  27.      
  28.       
  29.     //显示窗口及功能键  
  30.     public void display()  
  31.         System.out.println("显示窗口:" this.title);  
  32.         System.out.println("显示功能键:");  
  33.         for (Object obj functionButtons)  
  34.             System.out.println(((FunctionButton)obj).getName());  
  35.          
  36.         System.out.println("------------------------------");  
  37.         
  38.  
  39.   
  40. //功能键类:请求发送者  
  41. class FunctionButton  
  42.     private String name; //功能键名称  
  43.     private Command command; //维持一个抽象命令对象的引用  
  44.       
  45.     public FunctionButton(String name)  
  46.         this.name name;  
  47.      
  48.       
  49.     public String getName()  
  50.         return this.name;  
  51.      
  52.       
  53.     //为功能键注入命令  
  54.     public void setCommand(Command command)  
  55.         this.command command;  
  56.      
  57.       
  58.     //发送请求的方法  
  59.     public void onClick()  
  60.         System.out.print("点击功能键:");  
  61.         command.execute();  
  62.      
  63.  
  64.   
  65. //抽象命令类  
  66. abstract class Command  
  67.     public abstract void execute();  
  68.  
  69.   
  70. //帮助命令类:具体命令类  
  71. class HelpCommand extends Command  
  72.     private HelpHandler hhObj; //维持对请求接收者的引用  
  73.       
  74.     public HelpCommand()  
  75.         hhObj new HelpHandler();  
  76.      
  77.       
  78.     //命令执行方法,将调用请求接收者的业务方法  
  79.     public void execute()  
  80.         hhObj.display();  
  81.      
  82.  
  83.   
  84. //最小化命令类:具体命令类  
  85. class MinimizeCommand extends Command  
  86.     private WindowHanlder whObj; //维持对请求接收者的引用  
  87.       
  88.     public MinimizeCommand()  
  89.         whObj new WindowHanlder();  
  90.      
  91.       
  92. //命令执行方法,将调用请求接收者的业务方法  
  93.     public void execute()  
  94.         whObj.minimize();  
  95.      
  96.  
  97.   
  98. //窗口处理类:请求接收者  
  99. class WindowHanlder  
  100.     public void minimize()  
  101.         System.out.println("将窗口最小化至托盘!");  
  102.      
  103.  
  104.   
  105. //帮助文档处理类:请求接收者  
  106. class HelpHandler  
  107.     public void display()  
  108.         System.out.println("显示帮助文档!");  
  109.      
  110.  

       为了提高系统的灵活性和可扩展性,我们将具体命令类的类名存储在配置文件中,并通过工具类XMLUtil来读取配置文件并反射生成对象,XMLUtil类的代码如下所示:

  1. import javax.xml.parsers.*;  
  2. import org.w3c.dom.*;  
  3. import org.xml.sax.SAXException;  
  4. import java.io.*;  
  5.   
  6. public class XMLUtil  
  7. //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象,可以通过参数的不同返回不同类名节点所对应的实例  
  8.     public static Object getBean(int i)  
  9.         try  
  10.             //创建文档对象  
  11.             DocumentBuilderFactory dFactory DocumentBuilderFactory.newInstance();  
  12.             DocumentBuilder builder dFactory.newDocumentBuilder();  
  13.             Document doc;                             
  14.             doc builder.parse(new File("config.xml"));   
  15.           
  16.             //获取包含类名的文本节点  
  17.             NodeList nl doc.getElementsByTagName_r("className");  
  18.             Node classNode null 
  19.             if (0 == i)  
  20.                 classNode nl.item(0).getFirstChild();  
  21.              
  22.             else  
  23.                 classNode nl.item(1).getFirstChild();  
  24.               
  25.   
  26.             String cName classNode.getNodeValue();  
  27.               
  28.             //通过类名生成实例对象并将其返回  
  29.             Class Class.forName(cName);  
  30.             Object obj c.newInstance();  
  31.             return obj;  
  32.             
  33.         catch(Exception e){  
  34.             e.printStackTrace();  
  35.             return null 
  36.          
  37.      
  38.  

      配置文件config.xml中存储了具体建造者类的类名,代码如下所示: