工厂模式/代理模式/cglib动态代理

1、工厂模式详解

1.1、概述
工厂模式是Java中最常用的模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。它使用工厂创建对象,从而避免了手动创建对象,从而对底层代码进行了封装隐藏,只需要对外暴露创建对象所需的接口,便可进行对象的创建。
1.2、普通工厂模式
思路: 对于一个接口,在不同情况下需要不同的实现类,从而使用不同的功能。并通过工厂集中管理这些实现类的实例化,使得需要哪种实现类,只需通过相应的代号(可为各种自定义代号,如名称、编号等)从工厂中提取。
示例:

public class TestMain {
	public static void main(String[] args) {
		FactoryManage.getUse(1);
		FactoryManage.getUse(2);
	}
}

//接口
interface Water{
	public void useWater();
}

//实现一
class TakeShower implements Water{
	TakeShower(){
		useWater();
	}
	public void useWater() {
		System.out.println("take a shower!");
	}
}
//实现二
class DrinkWater implements Water{
	DrinkWater() {
		useWater();
	}
	public void useWater() {
		System.out.println("drink water!");
	}
}

//工厂管理
class FactoryManage{
	public static Water getUse(int useNum) {
		switch (useNum) {
		case 1:
			return new TakeShower();
		case 2:
			return new DrinkWater();
		default:
			return null;
		}
	}
}

1.3、抽象工厂模式
思路: 是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
示例:

public class TestMain {
	public static void main(String[] args) {
		FactoryProducer.getFactory(1).getWater(1);
	}
}

//接口
interface Water{
	public void useWater();
}

//实现一
class TakeShower implements Water{
	TakeShower(){
		useWater();
	}
	public void useWater() {
		System.out.println("take a shower!");
	}
}
//实现二
class DrinkWater implements Water{
	DrinkWater() {
		useWater();
	}
	public void useWater() {
		System.out.println("drink water!");
	}
}

//创建抽象类获取工厂
abstract class FactroyGet{
	public abstract Water getWater(int useNum);
}

//工厂管理
class WaterFactoryManage extends FactroyGet{

	@Override
	public Water getWater(int useNum) {
		// TODO Auto-generated method stub
		switch (useNum) {
		case 1:
			return new TakeShower();
		case 2:
			return new DrinkWater();
		default:
			return null;
		}
	}
	
}

//工厂生成器类
class FactoryProducer{
	public static FactroyGet getFactory(int factoryNum) {
		switch(factoryNum) {
			case 1:
				return new WaterFactoryManage();
			default:
				return null;	
		}
	}
}

2、代理模式详解

2.1、概述
一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。代理模式提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
2.2、静态代理
概述: 是由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.。
缺陷: 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
示例:


public class TestMain {
	public static void main(String[] args) {
		BuyBook buyBook = new BuyBook();
		TranBook tranBook = new TranBook();
		
		ProxyBook proxyBook = new ProxyBook(buyBook, tranBook);
		proxyBook.getBook();
	}
}

//行为接口
interface GetBook{
	public void getBook();
}

//目标对象
class BuyBook implements GetBook {
	public void getBook() {
		System.out.println("买一本书");
	}
}

//事务
class TranBook {
	public void payBook() {
		System.out.println("吊用支付宝支付");
	}
	public void sendBook() {
		System.out.println("顺丰快递运输");
	}
}

//代理类
class ProxyBook implements GetBook{
	
	BuyBook buyBook;
	TranBook tranBook;
	
	ProxyBook(BuyBook buyBook,TranBook tranBook){
		this.buyBook = buyBook;
		this.tranBook = tranBook;
	}

	public void getBook() {
		tranBook.payBook();
		tranBook.sendBook();
		buyBook.getBook();
	}
	
}

2.3、动态代理(JDK代理,接口代理)
概述:
1.代理对象,不需要实现接口,但是目标对象需要实现接口。
2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)因此,动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
3、静态代理在开始前就已经定义好了代理类,而动态代理在运行过程中才去指定,如果目标对象发生变化,动态代理只需要去修改或创建对象,而动态代理还需要对代理类进行操作。
示例:
说明:
(1)拦截器第一个属性为Object类型是为了方面目标对象的修改和改变;
(2)invoke方法的实现就是动态定义代理类(各参数含义如图示);
(3)invoke的运行是在代理对象调用指定方法时自动运行的。

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

public class TestMain {
	public static void main(String[] args) {
		Book buyBook = new BuyBook();
		Pen buyPen = new BuyPen();
		TranBuy tranBuy = new TranBuy();
		ProxyBuy proxyBuy = new ProxyBuy(buyBook, tranBuy);
		
		Book bookBuy = (Book) Proxy.newProxyInstance(proxyBuy.getClass().getClassLoader(), buyBook.getClass().getInterfaces(), proxyBuy);
		bookBuy.getBook();
		
		ProxyBuy proxyBuy2 = new ProxyBuy(buyPen, tranBuy);
		Pen penBuy = (Pen) Proxy.newProxyInstance(proxyBuy2.getClass().getClassLoader(), buyPen.getClass().getInterfaces(), proxyBuy2);
		penBuy.getPen();
	}
}

//目标对象A接口
interface Book{
	public void getBook();
}

//目标对象A
class BuyBook implements Book{
	public void getBook() {
		System.out.println("买一本书");
	}
}

//目标对象B接口
interface Pen{
	public void getPen();
}

//目标对象B
class BuyPen implements Pen{
	public void getPen() {
		System.out.println("买一只钢笔");
	}
}

//事务
class TranBuy {
	public void payBook() {
		System.out.println("吊用支付宝支付");
	}
	public void sendBook() {
		System.out.println("顺丰快递运输");
	}
}

//动态代理类
class ProxyBuy implements InvocationHandler{
	
	private Object targetObj;
	private TranBuy tranBuy;
	
	public ProxyBuy(Object targetObj,TranBuy tranBuy) {
		this.targetObj = targetObj;
		this.tranBuy = tranBuy;
	}
	
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		this.tranBuy.payBook();
		this.tranBuy.sendBook();
		method.invoke(targetObj, args);
		return null;
	}
	
}

2.4、.Cglib代理
概述: Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展。
1、JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现.
2、Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)
3、Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.。
示例:

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class TestMain {
	public static void main(String[] args) {
		BuyBook buyBook = new BuyBook();
		TranBuy tranBuy = new TranBuy();
		BuyBook proxy = (BuyBook) new ProxyCglib(buyBook, tranBuy).getProxyInstance();
		proxy.getBook();
	}
}

//目标对象A
class BuyBook {
	public void getBook() {
		System.out.println("买一本书");
	}
}

//事务
class TranBuy{
	public void pay() {
		System.out.println("调用支付宝支付");
	}
	public void send() {
		System.out.println("顺丰快递发货");
	}
}

//代理类
class ProxyCglib implements MethodInterceptor{
	
	private Object target;
	
	private TranBuy tranBuy;
	
	public ProxyCglib(Object target,TranBuy tranBuy) {
		this.target = target;
		this.tranBuy = tranBuy;
	}
	
	public Object getProxyInstance() {
		 //1.工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(target.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();
	}
	
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		tranBuy.pay();
		tranBuy.send();
		Object proxyObj = method.invoke(target, args);
		return proxyObj;
	}
	
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值