From: http://blog.csdn.net/dan_xp/archive/2007/10/11/1820852.aspx
最近一直在看java的设计模式 ,感觉印象最深刻的就是"面向接口编程",在java中,尽量多定义接口,因为设计的最重要的目的就是应对各种变化,而接口本身就是一种变化着的Class的直接反映,通过实现特定接口的各种具体类,达到应对变化的目的,下面以Proxy模式为例:
这是一个具体的卖鱼类,表示鱼10元/斤,如果这个类被用到系统中的时候,系统应对变化的灵活性就会大打折扣,请看如下:

public class SellFishSystem ...{
private SellFisher sellfish;
//...

public void sellFish() ...{
sellfish.sellFish();
}
}
如果以后鱼的价格变化,或者具体的卖鱼方法发生变化,就必须修改已经有的SellFisher的sellFish()的代码,这个情况
使得系统的可扩展性降低,我们肯定会想到解决方案了,定义一个接口,请看代码:

interface SellFisher ...{
int sellFish();
}

public class SellFishSystem ...{
private SellFisher sellfish;

public void sellFish() ...{
sellfish.sellFish();
}
}
我们所做的变化,只是把SellFisher从Class提升到Interface,这个时候好处自然很明显了,这个SellFisher本身就代表
了一种不确定,变化.大家在做开发的时候,阅读源代码的时候,肯定遇到过这种情况,总是跟踪类的对象看代码实现,如果发现了接口变量,就会比较郁闷,得了解它的具体实现类是什么,这个具体实现类的变化通常就可以应对需求的变化,系以及系统扩展.请看上例子,如果鱼的价格变化,或者具体的卖鱼方法发生变化,我们只需要新增加SellFisher的实现,
而不必修改已有的代码,对此我的理解是对系统来说,新增加一个类的代码风险要大大低于对已有类的代码的修改.我觉得这个也是设计模式的立足点吧(如果你喜欢修改已有代码,那么设计模式就没有多大意义了)
言归正传,有了上面的知识准备,我们接上面的例子来解释Proxy的模式就简单多了,比如现在鱼的价格变化,卖鱼的提示也发生变化了,我们需要一个新的Proxy类来实现
interface SellFisher {
int sellFish();
}
public class ConcreteSellFisher implements SellFisher {
public int sellFish() {
System.out.println("my fish is delicious!!");
return 10;
}
}
public class ProxySellFisher implements SellFisher {
private SellFisher sell;
public ProxySellFisher(SellFisher sell) {
this.sell = sell;
}
public int sellFish() {
System.out.println("the fish price higher");
return sell.sellFish()+10;
}
}
看上面,这个是Proxy模式的代码例子实现,我们现在在SellFishSystem 使用ProxySellFisher来卖鱼了,由ProxySellFisher再调用原来的ConcreteSellFisher类.具体的一些特征总结为:
1.有个代理类Proxy(和原来的实现类继承同一接口),该类里引用了原来的具体功能实现类(这里是ConcreteSellFisher)
2.重写实现方法,加一些新的变化的元素(比如鱼的价格上涨)
JDK里的Proxy类也实现了这个模式,只不过它叫动态代理,因为它的代理类变成了InvocationHandler了,执行的方法
是invoke了,从而变得更加灵活了,请看代码
public class ProxySellFisher implements InvocationHandler {
private SellFisher sell;
public ProxySellFisher(SellFisher sell) {
this.sell = sell;
}
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
System.out.println("the fish price higher");
return (Integer)method.invoke(sell, args)+10;
}
}
public class ClientTest {
public static void main(String args[]) {
SellFisher s = new ConcreteSellFisher();
InvocationHandler p = new ProxySellFisher(s);
Object obj = Proxy.newProxyInstance(s.getClass().getClassLoader(), s.getClass().getInterfaces(), p);
((SellFisher)obj).sellFish();
}
}
请注意,invoke(Object obj,Method method,Object[] args),这里的第一个参数obj其实可以看作没有用处的,不知道jdk为什么要把它也当作一个参数放这里,methd.invoke()方法,需要把原来的具体实现类作为参数传递进去,method.invoke(obj,args)相当于obj.method(args)
总结,从设计模式的角度讲,大家以后编程中,尽量要面向接口,更通俗一点就是,一个类中使用的别的对象成员变量,最好定义成接口的变量而不是实际实现类的变量
分享到:
相关推荐
**proxy.config** 是代理服务的配置文件,通常用于存放需要代理的服务列表或者设置其他高级选项。在ASP.NET的`proxy.ashx`中,这个文件可能包含对哪些URL进行代理的规则,以及认证信息等。对于Java和PHP版本的代理,...
Object proxy = Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); ``` 其中,`MyInvocationHandler`是你实现的`InvocationHandler`,`target`是你...
arcgis for javascript api所需要的配置文件,能解决跨域访问的问题,我在proxy....包含两个文件proxy.ashx,proxy.config两个文件,上次下载一个说是有两个文件,其实里面只有一个,有被骗了的感觉,所以这次上传上来
Nginx在vhost里的配置站点,通过proxy转发到动态域名的具体配置。 反向代理,动态域名 ,Proxy
chrome_proxy.exe
UPX_net.upx.proxy.browser_102_69.0.3497.100_.apk
* 动态代理中的静态方法:java.lang.reflect.Proxy.newProxyInstance (ClassLoader(类加载器),interface(接口),handler(监听处理器)) * * 代码示例:《帮爸爸买菜》 * 1.Father: 被代理类,必须需要实现接口 ...
这个是代理脚本 可以根据不同的ip决定是否访问代理服务器
在"InterfaceProxy"目录中,你可以看到如何利用`Proxy.newProxyInstance()`方法创建接口的代理对象,并通过实现`InvocationHandler`接口的`invoke()`方法来控制代理对象的行为。这种方式比静态代理更灵活,因为不...
proxy.py, 在 python 中,轻量级的HTTP代理服务器 proxy.pypython 中的轻量级HTTP代理服务器。特性作为单个文件模块分发除了 python 标准库之外没有依赖项支持 http,https,web sockets请求代理安装要简单安装 ...
《ArcGIS代理.Net版本proxy.ashx详解及应用》 ArcGIS代理(ArcGIS Proxy)是一种重要的GIS(地理信息系统)技术,它在.NET环境中实现,主要用于处理跨域访问限制问题,尤其是在ArcGIS服务与Web应用程序交互时。标题...
- **多代理切换**:对于需要频繁更换代理的用户,proxy.pac提供了一种自动化方式,可以根据需求动态选择合适的代理。 - **隐私保护**:通过proxy.pac,用户可以在访问特定网站时自动使用匿名代理,以保护个人信息不...
flex-messaging-proxy.jarflex-messaging-proxy.jarflex-messaging-proxy.jarflex-messaging-proxy.jar
- `Proxy.newProxyInstance()`是Proxy类的核心方法,用于创建代理对象。它需要三个参数:一个ClassLoader对象,一个接口数组,以及一个InvocationHandler实例。ClassLoader用于加载代理对象的类,接口数组指定了...
本文将详细解析如何在Tomcat环境下配置`proxy.cgi`作为代理。 首先,`proxy.cgi`是一种通用的HTTP代理脚本,通常用Perl或Python编写,用于处理跨域请求。在OpenLayers中,当需要通过JavaScript访问不同源的地图服务...
`dma-proxy.c`、`dma-proxy-test.c`、`dma-proxy.h` 这些文件名暗示了它们在实现或测试dma-proxy的功能中起到的作用: 1. `dma-proxy.c`: 这通常是一个C语言源代码文件,其中包含了dma-proxy的主要实现逻辑。它可能...
在上述代码中,`Proxy.newProxyInstance()`方法用于创建代理对象,它接收三个参数:类加载器、代理接口数组和InvocationHandler实例。当我们通过代理对象调用`doSomething()`方法时,实际会触发`MyInvocationHandler...