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

194 篇文章 13 订阅
189 篇文章 407 订阅

10.3  完整解决方案

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

         在图10-5中,Image充当抽象类,其子类JPGImagePNGImageBMPImageGIFImage充当扩充抽象类;ImageImp充当实现类接口,其子类WindowsImpLinuxImpUnixImp充当具体实现类。完整代码如下所示:
//像素矩阵类:辅助类,各种格式的文件最终都被转化为像素矩阵,不同的操作系统提供不同的方式显示像素矩阵
class Matrix {
	//此处代码省略
}

//抽象图像类:抽象类
abstract class Image {
	protected ImageImp imp;

	public void setImageImp(ImageImp imp) {
		this.imp = imp;
	} 

	public abstract void parseFile(String fileName);
}

//抽象操作系统实现类:实现类接口
interface ImageImp {
	public void doPaint(Matrix m);  //显示像素矩阵m
} 

//Windows操作系统实现类:具体实现类
class WindowsImp implements ImageImp {
    public void doPaint(Matrix m) {
    	//调用Windows系统的绘制函数绘制像素矩阵
    	System.out.print("在Windows操作系统中显示图像:");
    }
}

//Linux操作系统实现类:具体实现类
class LinuxImp implements ImageImp {
    public void doPaint(Matrix m) {
    	//调用Linux系统的绘制函数绘制像素矩阵
    	System.out.print("在Linux操作系统中显示图像:");
    }
}

//Unix操作系统实现类:具体实现类
class UnixImp implements ImageImp {
    public void doPaint(Matrix m) {
    	//调用Unix系统的绘制函数绘制像素矩阵
    	System.out.print("在Unix操作系统中显示图像:");
    }
}

//JPG格式图像:扩充抽象类
class JPGImage extends Image {
	public void parseFile(String fileName) {
        //模拟解析JPG文件并获得一个像素矩阵对象m;
        Matrix m = new Matrix(); 
        imp.doPaint(m);
        System.out.println(fileName + ",格式为JPG。");
    }
}

//PNG格式图像:扩充抽象类
class PNGImage extends Image {
	public void parseFile(String fileName) {
        //模拟解析PNG文件并获得一个像素矩阵对象m;
        Matrix m = new Matrix(); 
        imp.doPaint(m);
        System.out.println(fileName + ",格式为PNG。");
    }
}

//BMP格式图像:扩充抽象类
class BMPImage extends Image {
	public void parseFile(String fileName) {
        //模拟解析BMP文件并获得一个像素矩阵对象m;
        Matrix m = new Matrix(); 
        imp.doPaint(m);
        System.out.println(fileName + ",格式为BMP。");
    }
}

//GIF格式图像:扩充抽象类
class GIFImage extends Image {
	public void parseFile(String fileName) {
        //模拟解析GIF文件并获得一个像素矩阵对象m;
        Matrix m = new Matrix(); 
        imp.doPaint(m);
        System.out.println(fileName + ",格式为GIF。");
    }
}

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

<?xml version="1.0"?>
<config>
	<!--RefinedAbstraction-->
	<className>JPGImage</className> 
	<!--ConcreteImplementor-->
	<className>WindowsImp</className>
</config>

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

import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
public class XMLUtil {
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
	public static Object getBean(String args) {
		try {
			//创建文档对象
			DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = dFactory.newDocumentBuilder();
			Document doc;							
			doc = builder.parse(new File("config.xml")); 
			NodeList nl=null;
			Node classNode=null;
			String cName=null;
			nl = doc.getElementsByTagName("className");
			
			if(args.equals("image")) {
				//获取第一个包含类名的节点,即扩充抽象类
	            classNode=nl.item(0).getFirstChild();
	            
			}
			else if(args.equals("os")) {
			   //获取第二个包含类名的节点,即具体实现类
	            classNode=nl.item(1).getFirstChild();
			}
			
	         cName=classNode.getNodeValue();
	         //通过类名生成实例对象并将其返回
	         Class c=Class.forName(cName);
		  	 Object obj=c.newInstance();
	         return obj;		
           }   
           catch(Exception e) {
              e.printStackTrace();
              return null;
          }
     }
}

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

class Client {
	public static void main(String args[]) {
		Image image;
		ImageImp imp;
		image = (Image)XMLUtil.getBean("image");
		imp = (ImageImp)XMLUtil.getBean("os");
		image.setImageImp(imp);
		image.parseFile("小龙女");
	}
}

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

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

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

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

桥接模式是一种结构型设计模式,它将抽象和实现分离,使它们可以独立地变化桥接模式的核心思想是将一个大类或一组类分解成抽象和实现两个独立的维度,使它们可以独立地变化和扩展,同时通过桥接来将它们连接起来。 在C++桥接模式通常通过虚函数实现。抽象部分通过基类定义接口,而实现部分通过派生类实现具体的功能。通过将抽象部分的指针作为参数传递给实现部分的函数,就可以实现两个部分的连接。 下面是一个简单的桥接模式的C++示例: ```c++ class Implementor { public: virtual void operation() = 0; virtual ~Implementor() {} }; class ConcreteImplementorA : public Implementor { public: void operation() override { // 具体的实现A } }; class ConcreteImplementorB : public Implementor { public: void operation() override { // 具体的实现B } }; class Abstraction { public: Abstraction(Implementor* implementor) : m_implementor(implementor) {} virtual void operation() = 0; virtual ~Abstraction() {} protected: Implementor* m_implementor; }; class RefinedAbstraction : public Abstraction { public: RefinedAbstraction(Implementor* implementor) : Abstraction(implementor) {} void operation() override { m_implementor->operation(); // 其他操作 } }; int main() { Implementor* implementorA = new ConcreteImplementorA(); Implementor* implementorB = new ConcreteImplementorB(); Abstraction* abstractionA = new RefinedAbstraction(implementorA); Abstraction* abstractionB = new RefinedAbstraction(implementorB); abstractionA->operation(); abstractionB->operation(); delete abstractionA; delete abstractionB; delete implementorA; delete implementorB; return 0; } ``` 在上面的示例,Implementor是实现部分的抽象基类,ConcreteImplementorA和ConcreteImplementorB是具体的实现类。Abstraction是抽象部分的基类,RefinedAbstraction是抽象部分的具体实现类。在main函数,我们创建了不同的Implementor和Abstraction对象,并通过它们来完成不同的操作。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值