对于代理模式,他就是为一个实体类专门创建一个代理类,从客户端发来的对实体类的请求会直接发到代理类,通过代理类来调用实体类相应的方法。 网络上的专业解释: 在此模式中,一个类代表另一个类的功能,就是我们创建现有对象的对象,以便向外界提供功能接口。
实例:通过此模式调用不同品牌汽车的相应方法。
以下是我对此实例画的类图:
以下是对此实例所写的代码: 1.创建汽车接口,以及宝马和奔驰汽车的实现类
public interface Car {
void run();
}
public class BMW implements Car {
@Override
public void run() {
System.out.println("BMW running......");
}
}
public class Benz implements Car {
@Override
public void run() {
System.out.println("Benz running......");
}
}
2.创建宝马实现类的代理类
public class BMWProxy implements Car {
private BMW bmw;
public BMWProxy(BMW bmw) {
this.bmw = bmw;
}
@Override
public void run() {
bmw.run();
}
}
3.编写客户端代码进行测试
public class Test {
public static void main(String[] args) {
BMWProxy bmwProxy=new BMWProxy(new BMW());
bmwProxy.run();
}
}
4.后台输出
BMW running......
大家测试万以上代码的时候可以思考一下,代理类针对某一个实体类的,我现在是拥有两个实体,如果我拥有100个实体呢,这样的话,我们岂不是要创建100个代理类,所以对于以上而言,这种代理模式成为---静态代理模式,也就是把每个代理” 写死”的意思,这样的话,肯定是不利于我们以后程序的扩展的。 对于上面出现的问题,就出现了相应的解决办法,这种办法就叫---动态代理模式。 我们只在前面的例子上加两个类即可,已有代码不用改动,且看我的动态代理的代码:
创建一个动态的代理类(只要是实现于Car接口的实现类都可以自动产生自己对应的代理)
public class CarProxy implements InvocationHandler{
private Car car;
public CarProxy(Car car) {
this.car = car;
}
//参数: 被代理的对象 要调用的方法 调用方法时要的参数
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
//参数: 方法对应的类名 调用方法需要的参数
return method.invoke(car, args);
}
public Object getInstance(){
// 目标类 目标类的接口
return Proxy.newProxyInstance(car.getClass().getClassLoader(), car.getClass().getInterfaces(), this);
}
}
对,上面这个类就可以说是核心代码了,就是这个类解决了我们在静态代理模式所出现的” 扩展难”的问题,实现步骤: 1)此类实现InvocationHandler接口,并重写接口的invoke()方法 2)在invoke()方法中我们只要返回一句 method.invoke(委托类,调用此方法用的参数)即可,为了方便,我们在此类的构造器中就设置了他的委托类 3)在此类中新建一个方法,该方法就是生成委托类的代理类的,就一句话其中的参数是委托类的类加载器,代理类所要实现的接口,指派方法调用的处理程序,对于第三个参数,我想大家比较晕,第三个参数意思就是通过那个类调用的委托类的对应方法的,所以这个参数一般填的就是this 通过这么简单的几步,这个动态的代理类生成器就完成编写了,然后我们再写一个客户端测试类来验证一下:
public class Test {
public static void main(String[] args) {
CarProxy carPro=new CarProxy(new BMW());
Car bmw=(Car) carPro.getInstance();
bmw.run();
CarProxy carPro2=new CarProxy(new Benz());
Car benz=(Car) carPro2.getInstance();
benz.run();
}
}
后台显示内容:
BMW running......
Benz running......
对于代理模式,我们就按照动态代理模式来说吧,毕竟有了最优解了,大家也就不会用那个不优的了, 这种模式的优点是:扩展性高;客户端只能间接访问实体类,隐藏了实现类的细节 缺点:如果我们对实体有什么要扩展的话,代理类也要添加相应代码,这样的话就违反了”开闭原则”了,也提升了后期代码维护的复杂度。
总之还是那句话:没有完美的设计模式,只有将多种设计模式结合起来一块用,才可以起到”集百家之长”的效果。