操作复杂对象结构——访问者模式(三)

    Sunny软件公司开发人员使用访问者模式对OA系统中员工数据汇总模块进行重构,使得系统可以很方便地增加新类型的访问者,更加符合“单一职责原则”和“开闭原则”,重构后的基本结构如图26-3所示:

    在图26-3中,FADepartment表示财务部,HRDepartment表示人力资源部,它们充当具体访问者角色,其抽象父类Department充当抽象访问者角色;EmployeeList充当对象结构,用于存储员工列表;FulltimeEmployee表示正式员工,ParttimeEmployee表示临时工,它们充当具体元素角色,其父接口Employee充当抽象元素角色。完整代码如下所示:

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

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

    编写如下客户端测试代码:

    1. class Client
    2. {
    3. public static void main(String args[])
    4. {
    5. EmployeeList list = new EmployeeList();
    6. Employee fte1,fte2,fte3,pte1,pte2;
    7. fte2 = new FulltimeEmployee("杨过",2000.00,40);
    8. fte3 = new FulltimeEmployee("段誉",2400.00,38);
    9. pte1 = new ParttimeEmployee("洪七公",80.00,20);
    10. pte2 = new ParttimeEmployee("郭靖",60.00,18);
    11. list.addEmployee(fte1);
    12. list.addEmployee(fte2);
    13. list.addEmployee(fte3);
    14. list.addEmployee(pte1);
    15. list.addEmployee(pte2);
    16. Department dep;
    17. dep = (Department)XMLUtil.getBean();
    18. list.accept(dep);
    19. }
    20. }

    编译并运行程序,输出结果如下:

    1. <?xml version="1.0"?>
    2. <config>
    3. </config>

    重新运行客户端程序,输出结果如下:

    如果要在系统中增加一种新的访问者,无须修改源代码,只要增加一个新的具体访问者类即可,在该具体访问者中封装了新的操作元素对象的方法。从增加新的访问者的角度来看,访问者模式符合“开闭原则”。

    如果要在系统中增加一种新的具体元素,例如增加一种新的员工类型为“退休人员”,由于原有系统并未提供相应的访问接口(在抽象访问者中没有声明任何访问“退休人员”的方法),因此必须对原有系统进行修改,在原有的抽象访问者类和具体访问者类中增加相应的访问方法。从增加新的元素的角度来看,访问者模式违背了“开闭原则”。