侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

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

2023-12-17 星期日 / 0 评论 / 0 点赞 / 24 阅读 / 7949 字

今天给大家分享的是java设计模式之代理模式中的动态代理模式。如有不足,敬请指正。  我们上次说到静态代理使用一个代理类来管理被代理类对象(源对象)的统一处理,代理类必须要继承或者实现一个基类或者接口

  今天给大家分享的是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 实现动态代理,必须要使用接口来原始类的接口接收对象

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

广告 广告

评论区