Proxy.newProxyInstance()

from:http://blog.csdn.net/dan_xp/archive/2007/10/11/1820852.aspx

 

 最近一直在看java的设计模式 ,感觉印象最深刻的就是"面向接口编程",在java中,尽量多定义接口,因为设计的最重要的目的就是应对各种变化,而接口本身就是一种变化着的Class的直接反映,通过实现特定接口的各种具体类,达到应对变化的目的,下面以Proxy模式为例:

Proxy的模式最主要的目的,原有的类对象由于某种原因不能访问,需要通过一个新的类来间接地去实现,这个新的类就称为代理类,举个例子说明,老王买/卖鱼的例子
public   class  SellFisher  ... {
    
public int sellFish() ...{
        System.out.println(
"my fish is delicious!!");
        
return 10;
    }

}
这是一个具体的卖鱼类,表示鱼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)
总结,从设计模式的角度讲,大家以后编程中,尽量要面向接口,更通俗一点就是, 一个类中使用的别的对象成员变量,最好定义成接口的变量而不是实际实现类的变量
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`Proxy.newProxyInstance` 是 Java 中的一个方法,用于创建一个动态代理对象。它接受三个参数:一个类加载器,一个接口数组和一个 `InvocationHandler` 对象。动态代理对象可以在运行时动态地创建一个实现指定接口的代理类,并将方法调用委托给 `InvocationHandler` 来处理。 使用 `Proxy.newProxyInstance` 可以实现一些横切关注点(cross-cutting concerns)的功能,比如日志记录、性能监控、事务管理等。通过动态代理,可以在不修改原始类代码的情况下,为其增加额外的行为。 以下是一个简单的示例代码,演示如何使用 `Proxy.newProxyInstance` 创建一个动态代理对象: ```java public interface Foo { void bar(); } public class RealFoo implements Foo { @Override public void bar() { System.out.println("RealFoo: executing bar()"); } } public class LoggingHandler implements InvocationHandler { private final Object target; public LoggingHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method: " + method.getName()); Object result = method.invoke(target, args); System.out.println("After method: " + method.getName()); return result; } } public class Main { public static void main(String[] args) { Foo realFoo = new RealFoo(); InvocationHandler handler = new LoggingHandler(realFoo); Foo proxy = (Foo) Proxy.newProxyInstance( Foo.class.getClassLoader(), new Class[]{Foo.class}, handler); proxy.bar(); // 通过代理对象调用方法 } } ``` 运行上述代码,将会在控制台输出以下内容: ``` Before method: bar RealFoo: executing bar() After method: bar ``` 这说明 `LoggingHandler` 在方法调用前后添加了额外的日志输出行为。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值