文档章节

java设计模式之代理模式(动态代理)

404--Not--Found
 404--Not--Found
发布于 2019/05/13 22:17
字数 1140
阅读 1.3K
收藏 19

  今天给大家分享的是java设计模式之代理模式中的动态代理模式。如有不足,敬请指正。


  我们上次说到静态代理使用一个代理类来管理被代理类对象(源对象)的统一处理,代理类必须要继承或者实现一个基类或者接口!!(很笨重)。每个接口都要实现一个新的代理,每个方法的逻辑处理,还是要重复编写。

  那么动态代理:就是可以自由的不指定的使用任何接口来实现代理。所谓的动态就不需要指定代理类的固定接口。


  我们本次用模拟通过代理购买火车票来解释动态代理。

图示

一、创建实体类Ticket

package com.xkt.pojo;

import java.util.Date;

/**
 * @author lzx
 *
 */
public class Ticket {

	private int id;

	private String start; // 发出的

	private String destination; // 目的地

	private Date startTime; // 出发时间

	private float price; // 价格

	public Ticket() {
		super();
		// TODO Auto-generated constructor stub
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getStart() {
		return start;
	}

	public void setStart(String start) {
		this.start = start;
	}

	public String getDestination() {
		return destination;
	}

	public void setDestination(String destination) {
		this.destination = destination;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Ticket [id=" + id + ", start=" + start + ", destination=" + destination + ", startTime=" + startTime
				+ ", price=" + price + "]";
	}
}

二、创建一个公共接口TicketDao

package com.xkt.dao;

import java.util.Date;

import com.xkt.pojo.Ticket;

/**
 * @author lzx
 *
 */
public interface TicketDao {

	/**
	 * 售票的基础dao
	 * 
	 * @param start   出发地
	 * @param destination    目的地
	 * @param date    出发日期
	 * @param type    1:火车票  2:机票
	 * @return
	 */
	Ticket getTicket(String start,String destination,Date date);
}

三、创建其实现

3.1 TrainTicketDaoImpl

package com.xkt.dao.impl;

import java.util.Date;

import com.xkt.dao.TicketDao;
import com.xkt.pojo.Ticket;

/**
 * @author lzx
 *
 */
public class TrainTicketDaoImpl implements TicketDao {

	@Override
	public Ticket getTicket(String start, String destination, Date date) {

		Ticket t = new Ticket();

		// 模拟查询数据库,获取票信息
		t.setId(1);
		t.setDestination(destination);
		t.setStart(start);
		t.setStartTime(date);
		t.setPrice(300.0f);

		if ("武汉".equals(start) && "广州".equals(destination)) {
			t.setPrice(463.0f);
		} else if ("北京".equals(start) && "广州".equals(destination)) {
			t.setPrice(885.0f);
		} else {
			t.setPrice(500.0f);
		}

		System.out.println("---您已购买从 " + start + " 到 " + destination + " 的火车票,请注意发车时间---");

		return t;
	}

}

3.2 FlightTicketDaoImpl

package com.xkt.dao.impl;

import java.util.Date;

import com.xkt.dao.TicketDao;
import com.xkt.pojo.Ticket;

/**
 * @author lzx
 *
 */
public class FlightTicketDaoImpl implements TicketDao {

	@Override
	public Ticket getTicket(String start, String destination, Date date) {

		Ticket t = new Ticket();

		// 模拟查询数据库,获取票信息
		t.setId(1);
		t.setDestination(destination);
		t.setStart(start);
		t.setStartTime(date);
		t.setPrice(300.0f);

		if ("武汉".equals(start) && "广州".equals(destination)) {
			t.setPrice(1000.0f);
		} else if ("北京".equals(start) && "广州".equals(destination)) {
			t.setPrice(2000.0f);
		} else {
			t.setPrice(500.0f);
		}

		System.out.println("---您已购买从 " + start + " 到 " + destination + " 的机票,请注意起飞时间---");

		return t;

	}

}

四、创建代理类YellowCrow

package com.xkt.proxy;

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

import com.xkt.pojo.Ticket;

/**
 * @author lzx
 *
 */
public class YellowCrow implements InvocationHandler {

	// 1、指定代理源(被代理对象)
	private Object source;

	// 2、创建代理对象,其实就是黄牛本身
	public Object createProxy(Object source) {
		this.source = source;

		// 1、拿到接口
		Class<?>[] interfaces = source.getClass().getInterfaces();

		// 2、拿到classloader
		ClassLoader classLoader = source.getClass().getClassLoader();

		// 3、创建代理对象
		Object proxyInstance = Proxy.newProxyInstance(classLoader, interfaces, this);

		return proxyInstance;
	}

	// args:执行方法过程中的参数
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

		String start = (String) args[0];
		String destination = (String) args[1];
		Date date = (Date) args[2];

		// 通过代理,执行真正购票
		Ticket invoke = (Ticket) method.invoke(source, args);

		System.out.println("--黄牛加价100--");
		invoke.setPrice(invoke.getPrice() + 100);

		return invoke;
	}

}

五、测试

package com.xkt.test;

import java.util.Date;

import com.xkt.dao.TicketDao;
import com.xkt.dao.impl.FlightTicketDaoImpl;
import com.xkt.dao.impl.TrainTicketDaoImpl;
import com.xkt.pojo.Ticket;
import com.xkt.proxy.YellowCrow;

/**
 * @author lzx
 *
 */
public class TicketClient {

	public static void main(String[] args) {

		// 不通过代理购票,自己在12306上抢

		TicketDao tDao = new TrainTicketDaoImpl();
		/*
		 * Ticket ticket = tDao.getTicket("武汉", "广州", new Date());
		 * System.out.println(ticket);
		 */

		// 自己购票失败,只能找黄牛
		YellowCrow crow = new YellowCrow();
		TicketDao tDoProxy = (TicketDao) crow.createProxy(tDao);

		Ticket ticket2 = tDoProxy.getTicket("武汉", "广州", new Date());
		System.out.println(ticket2);

		testFlight();

	}

	private static void testFlight() {

		// 1、不通过黄牛,直接去官网购买
		TicketDao tDao = new FlightTicketDaoImpl();
		/*
		 * Ticket t1 = tDao.getTicket("武汉", "广州", new Date()); System.out.println(t1);
		 */

		// 通过黄牛购买
		YellowCrow crow = new YellowCrow();
		TicketDao createProxy = (TicketDao) crow.createProxy(tDao);

		Ticket t2 = createProxy.getTicket("武汉", "广州", new Date());
		System.out.println(t2);
	}
}

测试结果
  1. 可以看出可以不用创建多个代理对象
  2. 动态代理模式的好处,就是一个代理类可以代理多个种类型(接口不同)的对象
  3. 基于动态代理模式可以处理多个类型的类的对象,所以必须要使用到 JDK 的 Proxy 和InvocationHandler 来说实现
  4. 使用 JDK 自带的 API 实现动态代理,必须要使用接口来原始类的接口接收对象

版权说明:欢迎以任何方式进行转载,但请在转载后注明出处!

© 著作权归作者所有

404--Not--Found
粉丝 17
博文 32
码字总数 36781
作品 0
西安
程序员
私信 提问
加载中

评论(2)

404--Not--Found
404--Not--Found 博主

引用来自“莫在全”的评论

YellowCrow是什么鬼,黄乌鸦嘛?

😂😂😂黄牛,英语比较差
莫在全
莫在全
YellowCrow是什么鬼,黄乌鸦嘛?
设计模式3——Proxy设计模式

Proxy代理设计模式是一种控制对象访问的设计模式,类似于网络代理,网络代理机制如下图: Proxy代理设计模式机制如下: 代理模式UML图如下: 代理模式顺序图如下: 客户端程序通过代理程序来...

小米米儿小
2013/12/06
299
0
Java之23种设计模式解析(二)

B、结构模式(7 种) 我们接着讨论设计模式,上篇文章我讲完了 5 种创建型模式,这章开始,我将讲下 7 种结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模...

wersdffg
2015/02/15
178
0
设计模式知识汇总(附github分享)

写在前面 主要内容 为了更系统的学习设计模式,特地开了这样一个基于Java的设计模式【集中营】,都是笔者在实际工作中用到过或者学习过的一些设计模式的一些提炼或者总检。慢慢地初见规模,也...

landy8530
2018/10/10
0
0
设计模式 2014-12-19

book: 阎宏《JAVA与模式》 架构设计栏目 http://blog.csdn.net/enterprise/column.html 概要: http://bbs.csdn.net/forums/Embeddeddriver 23种设计模式分别是: 1.单例模式 2.工厂方法模式...

jayronwang
2014/12/19
341
0
设计模式15——Template Method设计模式

Template Method模板方法设计模式定义一个操作中算法的骨架,将具体步骤的执行延迟到子类中实现。Java中的抽象类就是使用了模板方法设计模式。模板方法设计模式结构如下: 以文档处理为例,T...

小米米儿小
2014/01/24
270
0

没有更多内容

加载失败,请刷新页面

加载更多

LeetCode.6.Z字形变换

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L C I R E T O E S I I G E D H N 之后,你的输出需...

tedzheng
25分钟前
41
0
使用postman测试接口,解决Session共享问题

问题: 在做登录模块时,使用Postman做接口测试,发现session不能共享问题:第一次请求将系统随机生成验证码放入Session中,第二次请求想要获取系统生成的验证码,但是取到的值为null,因此无...

code-ortaerc
58分钟前
67
0
从Maven存储库获取源JAR

有谁知道您是否可以在Maven存储库中找到源JAR? #1楼 如果您使用的是eclipse,则还可以打开“首选项”>“ Maven”并选择“下载Artifact源”,这将使pom.xml完整无缺,并将源或Java文档(如果...

技术盛宴
今天
60
0
CentOS 7 SSH连接超时自动断开解决方案

用SSH登录到Linux的时候,由于默认的连接超时时间很短,经常断开。可以修改配置文件调整服务器端向客户端请求消息的时间间隔,解决自动断开的问题。 编辑/etc/ssh/sshd_config 找到 #ClientA...

matrixchan
今天
53
0
非典期间的一段回忆

最近的新型肺炎病毒甚嚣尘上,已经成了大众最瞩目的事件,整个国家层面反应也算迅速,毕竟我们是一个十几亿人口的国家。 公众号的读者和我分享了一个一段03年非典期间的故事,感慨颇深。经原...

王知无
今天
65
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部