模式的本质就是不断重复出现的问题的可重用解决方案。一个完整的模式提供使用或者不使用该解决方案的理由,使用解决方案的结果,以及怎样实现该解决方案的建议。本文的模式总结仅描述问题的本质及其解决方案。
我要总结的前几个模式着重于类型,我称之为基础模式(Fundamental Patterns)。实际上,它们是基石,被广泛用于其它模式,或者被大量程序频繁使用。
接口(Interface)
一个常见问题就是你希望一个对象不需要知道另一个对象的类型就能够使用它所提供的服务。该问题的通常解决方案是让使用对象知道被使用对象实现了一个特定的接口,而不是让使用对象成为该特定类的一个实例。
例如,假设你正在编写一个购买商业货物的应用程序。你的程序需要知道诸如卖主、货运公司、交货地点以及发票地点等信息项。这些信息项所共有的一个特点就是它们都具有一个街道地址。这些街道地址将出现在用户接口的不同部分。你很可能希望有一个类来显示和编辑街道地址,以至于你可以在用户接口需要地址的任何地方重用它。我们把这个类叫做AddressPanel。
你希望AddressPanel对象能够在分别不同的独立数据对象中取出(get)和设置(set)地址信息。问题就随之而产生,AddressPanel类的哪个实例能够知道它们所使用的数据对象的类型。毫无疑问,你会使用不同的类来表示卖主,货运公司等等。如果你的程序使用的是支持多继承的语言所编写的,像C++,那么你就可以设计AddressPanel实例所用的数据对象继承一个地址类,另外还继承其他的类。如果你的程序使用的是像Java这样只支持单继承模式的语言,那么你必须探索其他解决方案。
你可以创建一个地址接口来解决这个问题。然后AddressPanel类实例简单的要求数据对象实现该地址接口。这样,AddressPanel类实例就可以调用数据对象的访问方法来取出(get)和设置(set)地址信息。使用接口提供的间接引用,AddressPanel类实例就可以调用数据对象的方法,而不需要知道它究竟属于哪个类。下面的类图说明了这些关系:
图1 间接通过地址接口
常量(Immutable)
在多个对象共享访问同一个对象的情况下,如果该共享对象的修改并没有完全在共享它的对象之间同步的话,那么就会出现问题。对一个对象进行同步修改需要小心编程,因为它很容易出错。如果修改和取出共享对象的状态是异步执行的,那么除了使Bug出现可能性增加以外,还使得正确的功能代码担负过多的对共享对象状态的同步访问。
常量模式(Immutable pattern)能够避免这些问题。它组织类能够使得类实例的状态信息在它构造后就不能改变。
假设你正在编写一个游戏程序,它包括对象在场地上的放置和随机移动。在程序类的设计过程中,你决定使用常量对象来表示对象在场地上的位置。位置建模的类组织图如下所示:
图2 常量Position
一个Position对象的所表示的位置被传递给它的构造函数。Position类有方法取得实例所表示的位置的x和y值。它特意没有设计方法来修改Position对象所表示的位置的x和y值。为了表示游戏场景的一个新位置,你必须创建一个新的Position对象。
一个最常用的Java API内核中类就是常量类java.lang.String。虽然常量模式(Immutable pattern)并不被其他大量模式所使用,但是它本质上比较基础,广泛用于Java的APIs中。另外,很多的程序中也经常使用它。
代理
代理模式具有多种表现形式。这类问题的目的是试图解决对一个提供服务的某个对象的访问进行管理的需求,并且对使用服务的对象来说是透明的。
代理对象代表另一个对象接收方法调用。客户对象调用代理对象的方法。代理对象的方法并不直接提供客户端所期望的服务。相反,代理对象的方法调用提供服务的真实对象。其结构如下图所示:
图3 通过代理的方法调用
虽然代理对象并不直接提供客户端所期望的服务,但是代理对象管理对这些服务的访问。代理对象通常与服务提供对象共享一个公共接口。无论客户对象是直接访问服务提供对象,还是通过代理来访问,它们都是通过公共接口来访问服务的,而不是作为一个特定类的实例来访问的。这就让客户对象不知道它们调用的是代理对象的方法,而不是调用真实的服务提供对象的方法。
图4 代理模式类图
代理对象可以提供多种不同类型的访问管理。一些比较重要的形式将在以后的文章中进行描述,下面是一些比较常用的代理形式:
l 编写一个需要花费很长时间才能完成的,但是看起来好像是立即返回的方法。
l 制造一种幻觉:一个存在于不同物理机器上的对象看起来好像是一个普通的本地对象。这种类型的代理被称作为远程代理(remote proxy)。它被用于RMI、CORBA以及其他对象请求代理。
l 根据安全策略控制对服务提供对象的访问。代理模式的这种用法称之为保护代理模式(Protection Proxy Pattern)。
l 制造一种幻觉:一个服务对象在它实际存在之前就已经存在了。如果一个服务对象的创建代价是昂贵的,并且它的服务并不是急需的,那么这种代理形式就非常适用。代理模式的这种用法称之为虚拟代理模式(Virtual Proxy Pattern)。
本文地址:http://com.8s8s.com/it/it17114.htm