设计模式——代理模式

代理模式(静态代理)

  1. 普通代理模式的核心就是,被代理对象和代理对象(共属一个接口),被代理对象要执行的操作由代理对象完成(此时被代理者需要手动new出来,再传递给代理者)。
  2. 普通代理模式还可以拓展,即调用时只见代理者而不见被代理者(更符合逻辑),被代理者的new由代理者完成。

普通代理 + 拓展

在这里插入图片描述

真实对象GamePlayer

public class GamePlayer implements IGamePlayer {
	private String name = "";
	// 通过构造函数传递名称
	public GamePlayer(String _name){
		this.name = _name;
	}

	public GamePlayer(IGamePlayer _gamePlayer,String _name){
		if (_gamePlayer == null) throw new RuntimeException("不能创建真实角色");
		else this.name = _name;
	}

	@Override
	public void login(String user, String password) {
		System.out.println("登录名为:" + user + "的用户" + this.name + "登录成功!");
	}

	@Override
	public void killBoss() {
		System.out.println(this.name + "打机械牛");
	}

	@Override
	public void upgrade() {
		System.out.println(this.name + "升了一级");
	}
}

代理对象

/**
 * 代练者
 */
public class GamePlayerProxy implements IGamePlayer {
	private IGamePlayer gamePlayer = null;

//    public GamePlayerProxy(IGamePlayer _gamePlayer){
//        this.gamePlayer = _gamePlayer;
//    }

	// 改动:不创建被代理对象,而直接创建代理对象,屏蔽了真实角色的变更对高层模型的影响
	public GamePlayerProxy(String name){
		try {
			gamePlayer = new GamePlayer(this,name);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void login(String user, String password) {
		this.gamePlayer.login(user, password);
	}
	@Override
	public void killBoss() {
		this.gamePlayer.killBoss();
	}
	@Override
	public void upgrade() {
		this.gamePlayer.killBoss();
	}
}

入口类

public class ProxyMain {
	public static void main(String[] args) {
		manual();   // 用户本人自己操作
		proxy();    // 代练操作
	}

	// 代练操作
	public static void proxy(){
//        GamePlayer player = new GamePlayer("Devilvan");
//        GamePlayerProxy player = new GamePlayerProxy(player);
		// 改动:不创建被代理对象,而直接创建代理对象,屏蔽了真实角色的变更对高层模型的影响
		GamePlayerProxy playerProxy = new GamePlayerProxy("Devilvan");
		playerProxy.login("Devilvan","123456");
		playerProxy.killBoss();
		playerProxy.upgrade();
	}

	// 用户本人自己操作
	public static void manual(){
		GamePlayerProxy player = new GamePlayerProxy("Devilvan");
		player.login("Devilvan","123456");
		player.killBoss();
		player.upgrade();
	}
}

结果

在这里插入图片描述

代理模式(强制代理)

  1. 必须通过真实角色获取代理角色才可以访问
  2. 例如:A找B办事,但是B让A去找代理人C,即A必须找到B指定的C才行。不经过B或不找C而去找其他代理D也是不行的

强制代理

接口

/**
 * 玩家接口
 */
public interface IGamePlayer2 {
	// 登录游戏
	public void login(String user,String password);
	// 打怪
	public void killBoss();
	// 升级
	public void upgrade();
	// 每个对象都可以获取自己指定的代理对象
	public IGamePlayer2 getProxy();
}

真实角色

public class GamePlayer2 implements IGamePlayer2 {
	private String name = "";
	// 我指定的代理对象
	private IGamePlayer2 proxy = null;

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


	// 获取代理对象
	public IGamePlayer2 getProxy(){
		this.proxy = new GamePlayerProxy2(this);
		return this.proxy;
	}

	private boolean isProxy(){
		return this.proxy != null;
	}

	@Override
	public void login(String user, String password) {
		if (isProxy()){
			System.out.println("登录名为:" + user + "的用户" + this.name + "登录成功!");
		} else {
			System.out.println("请使用指定的代理服务器");
		}
	}

	@Override
	public void killBoss() {
		if (isProxy()){
			System.out.println(this.name + "打机械牛");
		} else {
			System.out.println("请使用指定的代理服务器");
		}
	}

	@Override
	public void upgrade() {
		if (isProxy()){
			System.out.println(this.name + "升了一级");
		} else {
			System.out.println("请使用指定的代理服务器");
		}
	}
}

代理对象

public class GamePlayerProxy2 implements IGamePlayer2 {
	private IGamePlayer2 gamePlayer = null;

	public GamePlayerProxy2(IGamePlayer2 _gamePlayer){
		this.gamePlayer = _gamePlayer;
	}

	@Override
	public IGamePlayer2 getProxy() {
		return this;
	}

	@Override
	public void login(String user, String password) {
		this.gamePlayer.login(user, password);
	}
	@Override
	public void killBoss() {
		this.gamePlayer.killBoss();
	}

	@Override
	public void upgrade() {
		this.gamePlayer.upgrade();
	}
}

入口类

public class Proxy2Main {
	public static void main(String[] args) {
		visitReal();
		visitProxy();
		forceProxy();
	}

	// 强制代理
	// 结果:成功
	public static void forceProxy(){
		IGamePlayer2 evad = new GamePlayer2("Evad").getProxy();
		evad.login("Evad","loop");
		evad.killBoss();
		evad.upgrade();
	}

	// 直接访问代理类
	// 结果:被拦截
	public static void visitProxy(){
		GamePlayerProxy2 lisi = new GamePlayerProxy2(new GamePlayer2("Lisi"));
		lisi.login("lisi","123124");
		lisi.killBoss();
		lisi.upgrade();
	}

	// 直接访问真实角色
	// 结果:被拦截
	public static void visitReal(){
		GamePlayer2 zs = new GamePlayer2("张三");
		zs.login("张三","233939");
		zs.killBoss();
		zs.upgrade();
	}
}

结果

在这里插入图片描述

代理模式(代理的个性)

  1. 代理类除了实现与真实对象相同的接口外,还能实现其他的业务(接口),满足更多的需求

代理的个性

代理类个性接口

// 代理的个性
public interface IProxy {
	// 计算费用
	public void count();
}

代理类

public class GamePlayerProxy2 implements IGamePlayer2, IProxy {
	private IGamePlayer2 gamePlayer = null;

	public GamePlayerProxy2(IGamePlayer2 _gamePlayer){
		this.gamePlayer = _gamePlayer;
	}

	@Override
	public IGamePlayer2 getProxy() {
		return this;
	}

	@Override
	public void login(String user, String password) {
		this.gamePlayer.login(user, password);
	}
	@Override
	public void killBoss() {
		this.gamePlayer.killBoss();
	}

	@Override
	public void upgrade() {
		this.gamePlayer.upgrade();
		// 代理的个性,升级需要收费
		this.count();
	}

	@Override
	public void count() {
		System.out.println("升一级+5元");
	}
}

代理模式(动态代理)

  1. 动态代理在实现阶段不用关心代理对象是谁,而在运行阶段才指定代理的是哪个对象
  2. 动态代理需要实现InvocationHandler接口,作用相当于代理类

动态代理

代理类

/**
 * 动态代理,必须实现InvocationHandler接口
 */
public class GamePlayInvocationHandler implements InvocationHandler {
	// 被代理者
	Class<?> clz = null;
	// 被代理的实例
	Object obj = null;

	public GamePlayInvocationHandler(Object _obj){
		this.obj = _obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = method.invoke(obj, args);
		// (AOP实现通知)如果是登录方法,则发送信息
		if (method.getName().equalsIgnoreCase("login")){
			System.out.println("有人在使用我的账号!");
		}
		return result;
	}
}

入口类

public class InvocationHandlerMain {
	public static void main(String[] args) {
		GamePlayer player = new GamePlayer("Van DarkHomle");
		GamePlayInvocationHandler handler = new GamePlayInvocationHandler(player);
		ClassLoader cl = player.getClass().getClassLoader();
		IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl, new Class[]{IGamePlayer.class}, handler);
		proxy.login("Van DarkHomle","What you see");
		proxy.killBoss();
		proxy.upgrade();
	}
}

结果

在这里插入图片描述

代理模式(动态代理通用模型)

  1. 核心部分为自定义的Handler、Proxy和通知
  2. 其中proxy还可以根据业务需要进行定制

动态代理通用模型

在这里插入图片描述

Handler

public class MyInvocationHandler implements InvocationHandler {
	private Object target = null;
	public MyInvocationHandler(Object _obj){
		this.target = _obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		return method.invoke(target, args);
	}
}

Proxy及其子类

public class DynamicProxy<T> {
	public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) {
		// 寻找JoinPoint连接点,AOP框架使用元数据定义
		(new BeforeAdvice()).exec();
		return (T) Proxy.newProxyInstance(loader, interfaces, h);
	}
}

public class SubjectDynamicProxy extends DynamicProxy{
	public static <T> T newProxyInstance(Subject subject){
		ClassLoader classLoader = subject.getClass().getClassLoader();
		Class<?>[] interfaces = subject.getClass().getInterfaces();
		InvocationHandler handler = new MyInvocationHandler(subject);
		return newProxyInstance(classLoader,interfaces,handler);
	}
}

业务类(抽象主题)及其实现类

/**
 * 抽象主题
 */
public interface Subject {
	// 业务操作
	public void doSomething(String str);
}

public class RealSubject implements Subject {
	@Override
	public void doSomething(String str) {
		System.out.println("do something ---------> " + str);
	}
}

AOP通知类及其实现类

public interface IAdvice {
	// 通知只有一个方法,执行
	public void exec();
}

public class BeforeAdvice implements IAdvice {
	@Override
	public void exec() {
		System.out.println("这里是前置通知");
	}
}

入口类

public class GeneralDynamicProxyMain {
	public static void main(String[] args) {
		Subject subject = new RealSubject();
		InvocationHandler handler = new MyInvocationHandler(subject);
		// 定义主题的代理
		Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler);
		// 代理行为
		proxy.doSomething("Finish..");
		System.out.println("------------具体业务的动态代理------------");
		Subject proxy2 = SubjectDynamicProxy.<Subject>newProxyInstance(subject);
		proxy2.doSomething("Finish2...");
	}
}

结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加把劲骑士RideOn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值