二哈谈设计模式之代理模式

代理模式



前言

  • 核心作用:
    通过代理,控制对对象的访问!
    可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。(即:AOP的微观实现!)
  • AOP(Aspect Oriented Programming面向切面编程)的核心实现机制!
  • 核心角色:
    抽象角色
    定义代理角色和真实角色的公共对外方法真实角色
    实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
    关注真正的业务逻辑!
    代理角色
    实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作

一、静态代理

1.抽象对象

package proxy.staticProxy;

/**
 * 接口(明星行为)
 */
public interface Star {
    /**
     * 面谈
     */
    void confer();
    /**
     * 签合同
     */
    void signContract();
    /**
     * 订票
     */
    void bookTicket();
    /**
     * 唱歌
     */
    void sing();
    /**
     * 收钱
     */
    void collectMoney();
}

2.真实对象

package proxy.staticProxy;

/**
 * 真实对象
 */
public class RealStar implements Star {

    @Override
    public void bookTicket() {
        System.out.println("RealStar.bookTicket()");
    }

    @Override
    public void collectMoney() {
        System.out.println("RealStar.collectMoney()");
    }

    @Override
    public void confer() {
        System.out.println("RealStar.confer()");
    }

    @Override
    public void signContract() {
        System.out.println("RealStar.signContract()");
    }

    @Override
    public void sing() {
        System.out.println("RealStar(周杰伦本人).sing()");
    }

}

3.代理对象

package proxy.staticProxy;

/**
 * 代理对象
 */
public class ProxyStar implements Star {
	
	private Star star;
	
	public ProxyStar(Star star) {
		super();
		this.star = star;
	}

	@Override
	public void bookTicket() {
		System.out.println("ProxyStar.bookTicket()");
	}

	@Override
	public void collectMoney() {
		System.out.println("ProxyStar.collectMoney()");
	}

	@Override
	public void confer() {
		System.out.println("ProxyStar.confer()");
	}

	@Override
	public void signContract() {
		System.out.println("ProxyStar.signContract()");
	}

	@Override
	public void sing() {
		star.sing();
	}

}

4.测试类

package proxy.staticProxy;

/**
 * 测试类
 */
public class Client {
	public static void main(String[] args) {
		Star real = new RealStar();
		Star proxy = new ProxyStar(real);
		
		proxy.confer();
		proxy.signContract();
		proxy.bookTicket();
		proxy.sing();
		
		proxy.collectMoney();
		
	}
}

结果:
在这里插入图片描述

二、动态代理

1.抽象对象

package proxy.staticProxy;

/**
 * 接口(明星行为)
 */
public interface Star {
    /**
     * 面谈
     */
    void confer();
    /**
     * 签合同
     */
    void signContract();
    /**
     * 订票
     */
    void bookTicket();
    /**
     * 唱歌
     */
    void sing();
    /**
     * 收钱
     */
    void collectMoney();
}

2.真实对象

package proxy.staticProxy;

/**
 * 真实对象
 */
public class RealStar implements Star {

    @Override
    public void bookTicket() {
        System.out.println("RealStar.bookTicket()");
    }

    @Override
    public void collectMoney() {
        System.out.println("RealStar.collectMoney()");
    }

    @Override
    public void confer() {
        System.out.println("RealStar.confer()");
    }

    @Override
    public void signContract() {
        System.out.println("RealStar.signContract()");
    }

    @Override
    public void sing() {
        System.out.println("RealStar(周杰伦本人).sing()");
    }

}

3.动态代理(JDK自带)

package proxy.dynamicProxy;

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

/**
 * 动态生成代理类和对象
 */
public class StarHandler implements InvocationHandler {
	
	Star realStar;
	
	public StarHandler(Star realStar) {
		super();
		this.realStar = realStar;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object object = null;

		System.out.println("真正的方法执行前!");
		System.out.println("面谈,签合同,预付款,订机票");

		if(method.getName().equals("sing")){
			object = method.invoke(realStar, args);
		}
		System.out.println("真正的方法执行后!");
		System.out.println("收尾款");
		return object;
	}

}

4.代理对象

package proxy.dynamicProxy;

/**
 * 模拟动态生成的代理的结构
 * @author Administrator
 *
 */
public class ProxyStar implements Star {
	
	StarHandler handler;
	
	public ProxyStar(StarHandler handler) {
		super();
		this.handler = handler;
	}

	public void bookTicket() {
//		handler.invoke(this,当前方法 , args);
	}

	public void collectMoney() {
//		handler.invoke(this,当前方法 , args);
	}

	public void confer() {
//		handler.invoke(this,当前方法 , args);
	}

	public void signContract() {
//		handler.invoke(this,当前方法 , args);
	}

	public void sing() {
//		handler.invoke(this,当前方法 , args);
	}

}

5.测试类

package proxy.dynamicProxy;

import java.lang.reflect.Proxy;

public class Client {
	public static void main(String[] args) {
		
		Star realStar = new RealStar();
		StarHandler handler = new StarHandler(realStar);
		
		Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), 
				new Class[]{Star.class}, handler);
		
		proxy.sing();
		proxy.collectMoney();
		
	}
	
}

三、应用场景

  • 安全代理:屏蔽对真实角色的直接访问。
  • 远程代理:通过代理类处理远程方法调用(RMI) – 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。
  • 分类:
    – 静态代理(静态定义代理类)
    – 动态代理(动态生成代理类)
    • JDK自带的动态代理
    • javaassist字节码操作库实现
    • CGLIB
    • ASM(底层使用指令,可维护性较差)
  • 开发框架中应用场景:
    – struts2中拦截器的实现
    – 数据库连接池关闭处理
    – Hibernate中延时加载的实现
    – mybatis中实现拦截器插件
    – AspectJ的实现
    – spring中AOP的实现:日志拦截、 声明式事务处理
    – web service
    – RMI远程方法调用
    – …

四、面向切面AOP介绍

AOP(Aspect-Oriented Programming,面向切面的编程)
它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。它是一种新的方法论,它是对传统OOP编程的一种补充。
• 常用术语:
– 切面(Aspect):其实就是共有功能的实现。
– 通知(Advice):是切面的具体实现。
– 连接点(Joinpoint):就是程序在运行过程中能够插入切面的地点。
– 切入点(Pointcut):用于定义通知应该切入到哪些连接点上。
– 目标对象(Target):就是那些即将切入切面的对象,也就是那些被通知的对象
– 代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象。
– 织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。
• 开源的AOP框架
– Aspect

总结

优点:

  • 职责清晰:真实的角色就是实现的业务逻辑,无须关心其他非本职责的事务,通过后期的代理完成一件事务,附带的好处就是编程更加简洁清晰。
  • 高扩展性:具体主题角色是随时都会发生变化的,只要它实现了接口,不管它如何变化,都逃不脱接口的控制,我们的代理完全可以在不做任何修改的情况下使用。
  • 智能化:如Struts把表单映射到对象的过程。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值