设计模式——代理模式

代理模式(静态代理)

  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;}@Overridepublic void login(String user, String password) {System.out.println("登录名为:" + user + "的用户" + this.name + "登录成功!");}@Overridepublic void killBoss() {System.out.println(this.name + "打机械牛");}@Overridepublic 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();}}@Overridepublic void login(String user, String password) {this.gamePlayer.login(user, password);}@Overridepublic void killBoss() {this.gamePlayer.killBoss();}@Overridepublic 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;}@Overridepublic void login(String user, String password) {if (isProxy()){System.out.println("登录名为:" + user + "的用户" + this.name + "登录成功!");} else {System.out.println("请使用指定的代理服务器");}}@Overridepublic void killBoss() {if (isProxy()){System.out.println(this.name + "打机械牛");} else {System.out.println("请使用指定的代理服务器");}}@Overridepublic 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;}@Overridepublic IGamePlayer2 getProxy() {return this;}@Overridepublic void login(String user, String password) {this.gamePlayer.login(user, password);}@Overridepublic void killBoss() {this.gamePlayer.killBoss();}@Overridepublic 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;}@Overridepublic IGamePlayer2 getProxy() {return this;}@Overridepublic void login(String user, String password) {this.gamePlayer.login(user, password);}@Overridepublic void killBoss() {this.gamePlayer.killBoss();}@Overridepublic void upgrade() {this.gamePlayer.upgrade();// 代理的个性,升级需要收费this.count();}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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 {@Overridepublic void doSomething(String str) {System.out.println("do something ---------> " + str);}
}

AOP通知类及其实现类

public interface IAdvice {// 通知只有一个方法,执行public void exec();
}public class BeforeAdvice implements IAdvice {@Overridepublic 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...");}
}

结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/18736.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈关于智慧校园安全用电监测系统的设计

0引言 人生人身安全是大家关注的话题&#xff0c;2019年12月中国消防统计近五年发生在全国学生宿舍的火灾2314起&#xff08;中国消防2019.12.应急管理部消防救援局官方微博&#xff09;&#xff0c;违规电器是引发火灾的主因。如果在各寝室安装智能用电监测器实时监督线路参数…

IntelliJ IDEA安装教程

一、下载安装包 首先进入IDEA官网下载2021.2.1版本的安装包&#xff0c;不要问我为什么不下最新版&#xff0c;后面我会说。 二、安装与配置 打开安装包&#xff0c;安装完成后选择Evaluate for free&#xff08;免费试用&#xff09;&#xff0c;创建一个项目&#xff0c;进入…

ELK 企业级日志分析系统----elk的部署

文章目录 一、ELK 简介1.1 ElasticSearch介绍1.2 ELK的组件ElasticSearchKiabanaLogstash可以添加的其它组件 1.3 为什么要使用 ELK1.4 完整日志系统基本特征1.5 ELK 的工作原理&#xff1a; 二、elk环境部署2.1 ELK Elasticsearch 集群部署&#xff08;在Node1、Node2节点上操…

Django_模板标签语法

目录 引用变量 for循环标签 if条件标签 with标签 注释 extends和block标签 csrf_token标签 load static标签 源码等资料获取方法 引用变量 可以使用{{}}引用视图函数响应的变量和模板中的变量。 比如有如下视图函数 在模板中引用变量方式如下 界面展示如下 for循环标…

【Rust日报】2023-07-10 Flutter 中使用 Rust

Rust In Flutter 这个 high-level 封装包简化了Rust集成到你的Flutter应用程序中的过程&#xff0c;无需代码生成或本地工具。它考虑到易用性、未来的可扩展性和卓越的性能&#xff0c;处理所有复杂的后台工作。只需将此包添加到您的 Flutter 项目中&#xff0c;你就可以开始编…

Simulink 自动代码生成System Composer的使用Architecture Model

目录 前言 已有模型转换成架构模型&#xff08;Architecture Model&#xff09; 架构模型生成代码步骤 总结 前言 前面已经介绍了AUTOSAR架构模型怎么去搭建&#xff0c;参考下文&#xff1a; Simulink代码生成&#xff1a;Autosar模型及代码生成_simulink autosar_卡洛斯…

STM32 Proteus仿真水箱水塔水位温度控制系统DS18B20 -0065

STM32 Proteus仿真水箱水塔水位温度控制系统DS18B20 -0065 Proteus仿真小实验&#xff1a; STM32 Proteus仿真水箱水塔水位温度控制系统DS18B20 -0065 功能&#xff1a; 硬件组成&#xff1a;STM32F103C8单片机 LCD1602显示器ADC220V转3.3V电路DS18B20温度多个按键&#xf…

mac上 如何批量在文件名中插入文字

mac上 如何批量在文件名中插入文字&#xff1f;在使用Mac电脑的时候&#xff0c;我们经常需要对大量文件的名称进行修改&#xff0c;例如需要在大量文件的名称中插入一些相同的文字或者字符的时候&#xff0c;你会用什么方法来完成这项工作呢&#xff1f;相信很多人就面对过类似…

校园网免认证/校园网pojie

我们的目标是xiao yuan wang pojie 我们使用一个简单的python脚本&#xff0c;用于jiechu /pojie校园网只能登录一台手机和一台电脑的限制&#xff0c;仅供学习。 原理 我们利用已有可正常上网的校园网账户作为跳板&#xff0c;连上网后在后台下线账号所登录的设备&#xff0…

Python3,6行代码,搞定网络测速神器,我直接卸载某60测速器。

6行代码搞定网络测速器 1、引言2、代码实战2.1 介绍2.2 安装2.3 示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;你知道speedtest 这个库吗&#xff1f; 小鱼&#xff1a;嗯&#xff0c;知道一点点&#xff0c;咋了&#xff1f; 小屌丝&#xff1a;那你教教我怎么使…

【输入法篇】关闭微软输入法烦人的必应的文本建议设置

【输入法篇】关闭微软输入法烦人的必应的文本建议设置 额&#xff0c;微软输入法设置路径藏得有点深&#xff0c;建议在设置里面直接搜索进入&#xff0c;方便些&#xff01;—【蘇小沐】 文章目录 【输入法篇】关闭微软输入法烦人的必应的文本建议设置1.实验环境 &#xff08…

MySQL_2

目录 一、函数 1、字符串函数 2、数值函数 3、日期函数 4、流程控制函数 二、约束 1、概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 2、目的&#xff1a;保证数据库中数据的正确、有效性和完整性。 3、分类 4、外键约束 4…