首页 > 其他分享 >代理模式

代理模式

时间:2023-08-08 20:02:08浏览次数:34  
标签:Station 角色 Object 代理 模式 station public

静态代理

静态代理:

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

设计思路:定义一个抽象角色,让代理角色和真实角色分别去实现它。

1.抽象角色:声明真实对象和代理对象的共同接口。

2.真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。它只关注真正的业务逻辑。

3.代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作

静态代理实现:

package HeadFirstDesignMode.proxy;

/**
 * 描述:代理模式-静态代理
 */
public class StaticProxyPattern {
    public static void main(String[] args) {
        Station trainStation = new TrainStationImpl("xxx车站");

        // 客户端直接操作代理类,避免了客户端与真实类的直接交涉
        Station station = new StationProxy(trainStation);
        station.sellTickets();
        station.transport();
    }
}

// 抽象角色-车站接口
interface Station {
    void sellTickets();//卖票

    void transport();//运输
}

// 真实角色-车站接口实现类
class TrainStationImpl implements Station {
    private String name;

    public TrainStationImpl(String name) {
        this.name = name;
    }

    @Override
    public void sellTickets() {
        System.out.println(name + "卖票。。。");
    }

    @Override
    public void transport() {
        System.out.println(name + "运输乘客。。。");
    }
}

// 代理角色-作为火车站的一个代理类供客户端调用
class StationProxy implements Station {
    Station station;
    public StationProxy(Station station) {
        this.station = station;
    }

    @Override
    public void sellTickets() {
        station.sellTickets();//代理类中调用真实角色的方法
    }

    public void otherOperate() {
        System.out.println("代理类的额外操作。。。");
    }

    @Override
    public void transport() {
        // 车站代理不能运输,调用真实角色进行运输
        station.transport();
    }
}

动态代理

静态代理模式中,真实角色必须是事先已经存在的,并将其作为代理对象的内部属性,并且真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀。那么,如果事先并不知道真实角色,该如何使用代理呢?

这个问题可以通过Java的动态代理类来解决。动态代理必需用到以下两个类。

**(1).Interface InvocationHandler:**该接口中仅定义了一个方法Object invoke(Object obj, Method method, Object[] args)用于完成真实角色中方法的调用。

**(2).Proxy:**该类即为动态代理类,作用类似于静态代理模式的代理类

动态代理实现:

package HeadFirstDesignMode.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 描述:代理模式-动态代理
 */
public class DynamicProxyPattern {
    public static void main(String[] args) {
        Station stationImpl = new TrainStationImpl("杭州东站");//将要被代理的真实对象
        /**
         * 动态代理就好处在这里,不管这里是要代理什么对象,I
         * nvocationHandlerImpl与Proxy中代码都不必改变,
         * 都是用下面同样的方式去产生代理对象
         */
        InvocationHandler handler = new InvocationHandlerImpl(stationImpl);
        //用InvocationHandler的实现类包装真实的被代理角色
        ClassLoader loader = handler.getClass().getClassLoader();
        //获取当前java程序的类装载器Classloader
        Class[] interfaces = stationImpl.getClass().getInterfaces();
        //获取被代理角色实现的所有接口
        /**
         * Proxy类是动态代理模式涉及到的另一个重要的类,该类即为动态代理类,作用类似于静态代理模式中的代理类StationProxy,
         * 它有一个重要方法newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler handler):		   * 返回代理类的一个实例。
         * 其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组,handler是调用处理器InvocationHandler。
         * 传递此参数以使产生的代理对象可以当做真实类任意实现接口的子类来用。
         */
        Station station = (Station) Proxy.newProxyInstance(loader, interfaces, handler);
        station.sellTickets();//将会去执行DynamicProxy的invoke方法,完成对目标对象方法的调用
        station.transport();
    }
}


class InvocationHandlerImpl implements InvocationHandler {
    Object proxyobj;

    public InvocationHandlerImpl(Object object) {
        this.proxyobj = object;
    }

    @Override
    public Object invoke(Object obj, Method method, Object[] args)
            throws Throwable {
        System.out.println("start doing  .........");
        method.invoke(proxyobj, args);//调用被代理对象proxyobj的方法method,传入一个参数组args
        System.out.println("stop doing  .........");
        return null;
    }
}

cglib代理

我们知道Java中有一个动态代理(Proxy)也是做这个事情的,那我们为什么不直接使用Java动态代理,而要使用CGLIB呢?答案是CGLIB相比于JDK动态代理更加强大,JDK动态代理虽然简单易用,但是其有一个致命缺陷是,只能对接口进行代理。如果要代理的类为一个普通类、没有接口,那么Java动态代理就没法使用了。

Enhancer

Enhancer可能是CGLIB中最常用的一个类,和Java1.3动态代理中引入的Proxy类差不多。和Proxy不同的是,Enhancer既能够代理普通的class,也能够代理接口。Enhancer创建一个被代理对象的子类并且拦截所有的方法调用(包括从Object中继承的toString和hashCode方法)。Enhancer不能够拦截final方法,例如Object.getClass()方法,这是由于Java final方法语义决定的。基于同样的道理,Enhancer也不能对fianl类进行代理操作。这也是Hibernate为什么不能持久化final class的原因。

实现如下:

package HeadFirstDesignMode.proxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 描述:cglib代理模式
 */
public class CglibDemo implements MethodInterceptor {
    public Object getTarget() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(CglibTest.class);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        return methodProxy.invokeSuper(o, objects);
    }

    public static void main(String[] args) {
        CglibTest target = (CglibTest) new CglibDemo().getTarget();
        System.out.println(target.hello());
    }
}

class CglibTest {
    public String hello() {
        System.out.println("execute hello method");
        return "hello cglib";
    }
}

标签:Station,角色,Object,代理,模式,station,public
From: https://blog.51cto.com/u_11906056/7011752

相关文章

  • 迭代器模式
    我们登上并非我们选择的舞台,演出并非自己选择的剧本。——爱比荷泰**迭代器模式:**提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明的访......
  • 责任链模式
    **责任链模式:**使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。组成:抽象处理者角色(Handler):它定义了一个处理请求的接口。当然对于链子的不同实现,也可以在这个角色中实现后继链。......
  • SQlLite Wal 模式
    QLiteWAL(Write-AheadLogging)模式主要有以下几个优点:1.提高写入性能WAL模式将数据先写入日志文件,然后再定期更新到实际数据文件中。这避免了每次写入都要同步更新数据文件,大大提升了写入速度。2.提高并发性能WAL模式采用乐观锁并发控制,允许在同一数据库的多个连接中同......
  • java动态代理
    动态代理代理比较好理解,和现实生活中意思一样。就是我要干一件事情,可以通过代理人或代理平台进行完成,不需要直接和服务方接触。又或者计算机网络上说的代理。为什么叫动态代理?这里回到java程序上,是因为在运行时可以动态的创建接口的实现,通过java的反射进行实现。依赖三个关键类......
  • mongodb副本集模式的单机部署+修改ip
    环境:OS:Centos7mongodb:4.4.22 1.解压[root@localhostsoft]#tar-xvfmongodb-linux-x86_64-rhel70-4.4.22.tgz[root@localhostsoft]#mvmongodb-linux-x86_64-rhel70-4.4.22/usr/local/services/mongodb 2.创建目录mkdir-p/home/middle/mongodb/data/mkdir-p/ho......
  • 设计模式 solid原则
    SOLID原则是一组面向对象设计和编程的原则,旨在提供可维护、可扩展和可重用的代码。下面是SOLID原则的简要介绍:单一职责原则(SingleResponsibilityPrinciple,SRP):一个类应该只有一个引起变化的原因。换句话说,一个类应该只负责一个单一的功能或职责。开放封闭原则(Open-ClosedP......
  • kube-proxy 三种模式分析
    kube-proxy三种模式分析kubernetes上面的service资源的实现方式是由kube-proxy提供的模式决定的kube-proxy提供三种模式:userspace(Kubernetes1.2版本之前)、iptables、ipvs(推荐的)如果不满足ipvs时,会自动降为iptables模式再讲三种模式前,先简单说下Service的工作原理;在......
  • 代理IP与Socks5代理:跨界电商、游戏和爬虫领域的技术赋能与安全保障
    一、代理IP技术简介与特点代理IP技术是通过中间服务器转发网络请求,隐藏用户真实IP地址的技术。它可以实现匿名访问、突破封锁和数据隐私保护等功能。代理IP的分类:常见的代理IP类型包括HTTP代理、HTTPS代理和Socks代理,其中Socks5代理是最为灵活和高效的代理技术之一。二、Socks5代理......
  • 对现代电网变电运维管理模式的浅析--安科瑞张田田
    安科瑞张田田摘要:当前,随着经济建设的不断发展,我国电力企业的快速发展受到了推动。在电力企业发展过程中,变电运行维护管理是一项重要内容。管理模式的好坏直接关系到整个电网的稳定发展。因此,在现代变电运行管理过程中,需要提高管理水平,提升平平供电企业的持续稳定发展,为人民群众提供......
  • 设计模式(一)单例
    一、定义确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种创建型模式。在单例类的内部定义了一个静态对象,作为提供外部共享的唯一实例为了防止在外部对单例类实例化,它的构造函数被设为private在单例类......