处理多维度变化——桥接模式(三)

来源:互联网 发布:数据挖掘的必要性 编辑:程序博客网 时间:2024/06/03 19:56

10.3  完整解决方案

        为了减少所需生成的子类数目,实现将操作系统和图像文件格式两个维度分离,使它们可以独立改变,Sunny公司开发人员使用桥接模式来重构跨平台图像浏览系统的设计,其基本结构如图10-5所示:

         在图10-5中,Image充当抽象类,其子类JPGImagePNGImageBMPImageGIFImage充当扩充抽象类;ImageImp充当实现类接口,其子类WindowsImpLinuxImpUnixImp充当具体实现类。完整代码如下所示:
[java] view plaincopy
  1. //像素矩阵类:辅助类,各种格式的文件最终都被转化为像素矩阵,不同的操作系统提供不同的方式显示像素矩阵  
  2. class Matrix {  
  3.     //此处代码省略  
  4. }  
  5.   
  6. //抽象图像类:抽象类  
  7. abstract class Image {  
  8.     protected ImageImp imp;  
  9.   
  10.     public void setImageImp(ImageImp imp) {  
  11.         this.imp = imp;  
  12.     }   
  13.   
  14.     public abstract void parseFile(String fileName);  
  15. }  
  16.   
  17. //抽象操作系统实现类:实现类接口  
  18. interface ImageImp {  
  19.     public void doPaint(Matrix m);  //显示像素矩阵m  
  20. }   
  21.   
  22. //Windows操作系统实现类:具体实现类  
  23. class WindowsImp implements ImageImp {  
  24.     public void doPaint(Matrix m) {  
  25.         //调用Windows系统的绘制函数绘制像素矩阵  
  26.         System.out.print("在Windows操作系统中显示图像:");  
  27.     }  
  28. }  
  29.   
  30. //Linux操作系统实现类:具体实现类  
  31. class LinuxImp implements ImageImp {  
  32.     public void doPaint(Matrix m) {  
  33.         //调用Linux系统的绘制函数绘制像素矩阵  
  34.         System.out.print("在Linux操作系统中显示图像:");  
  35.     }  
  36. }  
  37.   
  38. //Unix操作系统实现类:具体实现类  
  39. class UnixImp implements ImageImp {  
  40.     public void doPaint(Matrix m) {  
  41.         //调用Unix系统的绘制函数绘制像素矩阵  
  42.         System.out.print("在Unix操作系统中显示图像:");  
  43.     }  
  44. }  
  45.   
  46. //JPG格式图像:扩充抽象类  
  47. class JPGImage extends Image {  
  48.     public void parseFile(String fileName) {  
  49.         //模拟解析JPG文件并获得一个像素矩阵对象m;  
  50.         Matrix m = new Matrix();   
  51.         imp.doPaint(m);  
  52.         System.out.println(fileName + ",格式为JPG。");  
  53.     }  
  54. }  
  55.   
  56. //PNG格式图像:扩充抽象类  
  57. class PNGImage extends Image {  
  58.     public void parseFile(String fileName) {  
  59.         //模拟解析PNG文件并获得一个像素矩阵对象m;  
  60.         Matrix m = new Matrix();   
  61.         imp.doPaint(m);  
  62.         System.out.println(fileName + ",格式为PNG。");  
  63.     }  
  64. }  
  65.   
  66. //BMP格式图像:扩充抽象类  
  67. class BMPImage extends Image {  
  68.     public void parseFile(String fileName) {  
  69.         //模拟解析BMP文件并获得一个像素矩阵对象m;  
  70.         Matrix m = new Matrix();   
  71.         imp.doPaint(m);  
  72.         System.out.println(fileName + ",格式为BMP。");  
  73.     }  
  74. }  
  75.   
  76. //GIF格式图像:扩充抽象类  
  77. class GIFImage extends Image {  
  78.     public void parseFile(String fileName) {  
  79.         //模拟解析GIF文件并获得一个像素矩阵对象m;  
  80.         Matrix m = new Matrix();   
  81.         imp.doPaint(m);  
  82.         System.out.println(fileName + ",格式为GIF。");  
  83.     }  
  84. }  

        为了让系统具有更好的灵活性和可扩展性,我们引入了配置文件,将具体扩充抽象类和具体实现类类名都存储在配置文件中,再通过反射生成对象,将生成的具体实现类对象注入到扩充抽象类对象中,其中,配置文件config.xml的代码如下所示:

[html] view plaincopy
  1. <?xml version="1.0"?>  
  2. <config>  
  3.     <!--RefinedAbstraction-->  
  4.     <className>JPGImage</className>   
  5.     <!--ConcreteImplementor-->  
  6.     <className>WindowsImp</className>  
  7. </config>  

        用于读取配置文件config.xml并反射生成对象的XMLUtil类的代码如下所示:

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

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

[java] view plaincopy
  1. class Client {  
  2.     public static void main(String args[]) {  
  3.         Image image;  
  4.         ImageImp imp;  
  5.         image = (Image)XMLUtil.getBean("image");  
  6.         imp = (ImageImp)XMLUtil.getBean("os");  
  7.         image.setImageImp(imp);  
  8.         image.parseFile("小龙女");  
  9.     }  
  10. }  

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

Windows操作系统中显示图像:小龙女,格式为JPG

        如果需要更换图像文件格式或者更换操作系统,只需修改配置文件即可,在实际使用时,可以通过分析图像文件格式后缀名来确定具体的文件格式,在程序运行时获取操作系统信息来确定操作系统类型,无须使用配置文件。当增加新的图像文件格式或者操作系统时,原有系统无须做任何修改,只需增加一个对应的扩充抽象类或具体实现类即可,系统具有较好的可扩展性,完全符合“开闭原则”。

【作者:刘伟  http://blog.csdn.net/lovelion】

原创粉丝点击