23种设计模式中的代理模式

本文详细介绍了代理模式的概念及其三种变体:远程代理、动态代理和保护代理。通过具体实例代码展示了如何实现这些代理模式,包括远程代理中使用RMI进行远程对象调用、动态代理中利用Java反射机制创建代理类以及保护代理中对方法调用的控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代理模式:为一个对象提供一个替身,以控制对这个对象的访问

被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象

代理模式有很多变体,都是为了控制与管理对象访问

①远程代理:远程对象的本地代表,通过它可以让远程对象当本地对象来调用。远程代理是通过网络和真正的远程对象沟通信息。

实例代码:

定义一个接口继承自Remote

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface MyRemote extends Remote{
    
    public State getState() throws RemoteException; 
    
}

定义一个继承该接口的类

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
    private Light light;
    
    protected MyRemoteImpl(Light light) throws RemoteException {
        super();
        // TODO Auto-generated constructor stub
    }

    @Override
    public State getState() throws RemoteException {
        return light.getState();
    }
    
    public static void main(String[] args) throws RemoteException, MalformedURLException {
        Light light=new Light();
        light.setState(State.On);
        MyRemoteImpl impl = new MyRemoteImpl(light);
        Naming.rebind("rmi:127.0.0.1:10023/RemoteGetState", impl);
    }

}

其中的Light.java

public class Light {
    private State state;

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }
    
}

State.java

public enum State {
    On,Off;
}

并且在main方法里面绑定了该远程服务

剩下的只需要在网络找寻找该远程服务就可以了

代码如下

public class MyRemoteClient {
    
    public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
        MyRemote remote = (MyRemote) Naming.lookup("rmi:127.0.0.1:10023/RemoteGetState");
        System.out.println(remote.getState());
    }
    
}

②动态代理:运行时动态地创建代理类,并将方法调用转发到指定类

 先定义一个接口IPerson.java

public interface IPerson {
    public int getAge();

    public void setAge(int age);

    public String getName();

    public void setName(String name);
}

再定义一个实现IPerson.java的类Person.java

public class Person implements IPerson{

    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

下面是动态代理的核心代码

public static void main(String[] args) {
        Person p = new Person();
        System.out.println(p);
        System.out.println("-------------------------------------");
        IPerson iPerson = (IPerson) Proxy.newProxyInstance(
                Person.class.getClassLoader(), Person.class.getInterfaces(),
                new PersonInvocationHandler(p));
        iPerson.setAge(12);
        System.out.println(iPerson);
        System.out.println(iPerson.getAge());
    }

其中的PersonInvocationHandler.java代码如下

public class PersonInvocationHandler implements InvocationHandler{
    
    private Person p;
    
    public PersonInvocationHandler(Person p){
        this.p=p;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        return method.invoke(p, args);
    }
    
}

运行结果如下;

可以看出,代理对象和被代理对象是同一片内存区域,也就是同一个对象。

③保护代理:对目标对象访问的控制和管理

保护代理实际上是动态代理,动态代理的代码不动,只动PersonInvocationHandler.java

代码如下

public class PersonInvocationHandler implements InvocationHandler{
    
    private Person p;
    
    public PersonInvocationHandler(Person p){
        this.p=p;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        if(method.getName().startsWith("set")){
            return new IllegalAccessException();
        }
        return method.invoke(p, args); 
} }

运行结果:

在方法里面我屏蔽了有关于set的方法,所以无论你set什么东西进去都不能成功的,但是get方法就可以

转载于:https://www.cnblogs.com/pig-brother/p/7301266.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值