java design patterns 6-- proxy mode

java design patterns 6-- proxy mode

1, proxy mode introduced:

1.1 Why learn proxy mode? This is because the underlying Aop of Spring! (SpringAop and SpringMvc)

1.2, proxy mode classification:

  • Static agents
  • Dynamic Proxy

1.3, proxy mode diagram (to rent an apartment, for example)

2, the static agent

2.1 Role analysis:

  1. Abstract role: generally use interfaces or abstract classes to solve
  2. Real role: the role of agent
  3. Proxy Client: Agent real role. After the agent's real role, we usually do a number of subsidiary operations
  4. Customer: people accessing the proxy object

2.2, Example 1 (Demo rent)

2.2.1, abstract role to achieve (the landlord abstract class)

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

/**
 * 租房
 */
public interface Rent {

    void rent();
}

2.2.2, the real role to achieve (the landlord's implementation class)

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

/**
 * 房东
 */
public class Host implements Rent {

    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

2.2.3, not rent by proxy

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

public class Client {
    public static void main(String[] args) {
        //直接找房东
        Host host = new Host();
        host.rent();
    }
}

operation result:

房东要出租房子!

2.2.4, malpractice

  1. In real life situations, the landlord may only sell, but not responsible for renting
  2. If you want to improve the success rate rent an apartment, we will inevitably need some other services, such as: showings, talk about the price, contracts, etc., which the landlord does not want to participate, thus creating an intermediary, that is the agent.

2.2.5, the agent appears

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

public class Proxy implements Rent {

    private Host host;

    public Proxy() {

    }

    public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        seeHouse();
        host.rent();
        fare();
        hetong();
    }

    //看房
    public void seeHouse() {
        System.out.println("中介代理看房");
    }

    //收中介费
    public void fare() {
        System.out.println("收中介费");
    }

    public void hetong() {
        System.out.println("签合同");
    }
}

2.2.6, to rent an apartment by proxy

package com.xgp.company.结构性模式.代理模式.静态代理.Demo1;

public class Client {
    public static void main(String[] args) {
/*        //直接找房东
        Host host = new Host();
        host.rent();*/

        //通过代理去租房子
        //房东要租房子
        Host host = new Host();
        //代理
        //中介帮房东租房子,但是,中介一半都会有一些附属操作
        Proxy proxy = new Proxy(host);
        proxy.rent();
    }
}

operation result:

中介代理看房
房东要出租房子!
收中介费
签合同

2.3 Analysis:

Benefits proxy mode

  1. You can make the operation more purely real character, not to pay attention to some of the public's business.
  2. Public business to the role agents to complete, to achieve the division of the business.
  3. Public service occurs when extended, easy centralized management.

Disadvantages:

  • A real role will have the role of an agent, doubling the amount of code, development efficiency is low.

2.4, Example 1 (deletions demonstrate change search service)

2.4.1, the abstract class writing service

package com.xgp.company.结构性模式.代理模式.静态代理.Demo2;

public interface UserService {
    void add();
    void del();
    void update();
    void query();
}

2.4.2, written service implementation class

package com.xgp.company.结构性模式.代理模式.静态代理.Demo2;

/**
 * 真实对象
 */
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void del() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("更新了一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询了一个用户");
    }
}

2.4.3, if at this time does not want to change the original code, and add functionality to print the log method, in which case the agent birth

package com.xgp.company.结构性模式.代理模式.静态代理.Demo2;

/**
 * 代理角色,增加日志的功能
 */
public class UserServiceProxy implements UserService {

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void add() {
        userService.add();
        log("add");
    }

    @Override
    public void del() {
        userService.del();
        log("del");
    }

    @Override
    public void update() {
        userService.update();
        log("update");
    }

    @Override
    public void query() {
        userService.query();
        log("query");
    }

    public void log(String msg) {
        System.out.println("使用了" + msg + "方法!");
    }
}

2.4.4 write client class, using the service approach, and print the log

package com.xgp.company.结构性模式.代理模式.静态代理.Demo2;

public class Client {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();

        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);

        proxy.add();
        proxy.del();
        proxy.update();
        proxy.query();
    }
}

operation result:

增加了一个用户
使用了add方法!
删除了一个用户
使用了del方法!
更新了一个用户
使用了update方法!
查询了一个用户
使用了query方法!

2.5 Reflection: In the actual business, the lateral development benefits

Can ensure the feasibility of the original code, will not carry out the destruction of the original version of the software, is compatible with the past.

3, dynamic proxies

3.1, dynamic proxies features

  1. Acting as dynamic and static agents
  2. Dynamic proxy proxy class is dynamically generated, not written by us directly

3.2, the classification of dynamic proxy implementation

  • --JDK dynamic proxy-based interface (this section describes the manner required)
  • Class-based: cglib
  • java bytecode: javasist

3.3 requires an understanding of two classes

  • Proxy: proxy class
  • InvocationHandler:调用处理程序类

具体的使用参照java的api

3.4、例1——房东租房的例子

3.4.1、房东的接口和实现类不变

3.4.2、实现自动生成代理的类

package com.xgp.company.结构性模式.代理模式.动态代理.Demo1;

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

/**
 * 等下我们会用这个类,自动生成代理类
 */
public class ProxyInvocationHandler implements InvocationHandler {

    /**
     * 被代理的接口
     */
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    /**
     * 获得一个代理
     * @return
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }

    /**
     * 处理代理实例,并放回结果
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //用反射来执行方法
        seeHouse();     //调用代理自身的方法
        //动态代理的本质,就是使用反射机制来实现
        Object result = method.invoke(rent, args);
        fare();
        hetong();
        return result;
    }

    public void seeHouse() {
        System.out.println("中介带看房子!");
    }

    //收中介费
    public void fare() {
        System.out.println("收中介费");
    }

    public void hetong() {
        System.out.println("签合同");
    }
}

3.4.3、实现客户端使用代理来租房子

package com.xgp.company.结构性模式.代理模式.动态代理.Demo1;

public class Client {
    public static void main(String[] args) {
        //真实角色
        Host host = new Host();

        //代理角色
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //通过调用程序处理角色,来处理我们要调用的接口对象
        pih.setRent(host);

        //放回代理类
        //这里的代理类就是动态生成的,我们并没有写他
        Rent proxy = (Rent) pih.getProxy();
        proxy.rent();
    }
}

运行结果:

中介带看房子!
房东要出租房子!
收中介费
签合同

3.5、例2——增删改查的例子

3.5.1、先来实现一个万能的代理生成类

package com.xgp.company.结构性模式.代理模式.动态代理.Demo2;

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

/**
 * 万能代理类
 */
public class ProxyInvocationHandler implements InvocationHandler {

    /**
     * 被代理的接口
     */
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    /**
     * 获得一个代理
     * @return
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    /**
     * 处理代理实例,并放回结果
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //用反射来执行方法
        //动态代理的本质,就是使用反射机制来实现
        Object result = method.invoke(target, args);
        log(method.getName());
        return result;
    }

    public void log(String msg) {
        System.out.println("使用了" + msg + "方法!");
    }
}

也就是将上一个例子的具体实现类——房东类,替换成Object类

3.5.2、UserService的接口和实现类不变

3.5.3、编写客户端类使用代理调用增删改查方法

package com.xgp.company.结构性模式.代理模式.动态代理.Demo2;

public class Client {
    public static void main(String[] args) {
        //真实角色
        UserService userService = new UserServiceImpl();
        //代理角色
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(userService);
        UserService proxy = (UserService) pih.getProxy();

        proxy.add();
        proxy.del();
        proxy.update();
        proxy.query();
    }
}

运行结果:

增加了一个用户
使用了add方法!
删除了一个用户
使用了del方法!
更新了一个用户
使用了update方法!
查询了一个用户
使用了query方法!

3.6、弊端分析:

虽然使用动态代理能够节省代码量,并且实现静态代理的全部优点。但是,动态代理的核心是反射技术,通过反射技术调用方法效率较大,因此也可能影响系统效率。

3.7、动态代理的好处

一个动态代理的是一个接口,一般就是对应的一类业务。

Guess you like

Origin www.cnblogs.com/xgp123/p/12308415.html