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;
}
}