JAVA 开发设计模式 - 笔记

chan 作者
阅读 329 喜欢 0

抽象工厂模式

抽象工厂 —生产—> 抽象产品
具体工厂继承抽象工厂重写方法 —生产—> 继承抽象产品的具体产品

如果要加入新的产品一族,比如说火车,那么只需要创建火车工厂类继承抽象工厂,重写相应的生产对象方法,然后创建火车类继承抽象产品,只需要更改创建的工厂为火车工厂,即可调用火车相关的方法。

/**
 * 抽象工厂
 * 
 * @author CHAN
 * @date 2020/05/01
 */
public abstract class AbstractFactory {
    public abstract AbstractProduct getProduct();
}
/**
 * 抽象产品 -> 产品是驾驶的
 *
 * @author CHAN
 * @date 2020/05/02
 */
public abstract class AbstractProduct {
    public abstract void drive();
}
/**
 * 火车类
 *
 * @author CHAN
 * @date 2020/05/02
 */
public class Train extends AbstractProduct{
    @Override
    public void drive() {
        System.out.println("开火车");
    }
}
/**
 * 具体工厂 -> 生产火车
 *
 * @author CHAN
 * @date 2020/05/02
 */
public class TrainFactory extends AbstractFactory{
    @Override
    public AbstractProduct getProduct() {
        return new Train();
    }
}
/**
 * 测试
 *
 * @author CHAN
 * @date 2020/05/01
 */
public class App {
    public static void main(String[] args) {
        AbstractFactory modern = new TrainFactory();
        modern.getProduct().drive();
    }
}

静态代理

创建交通工具接口,创建车类实现接口重写开车方法
创建代理类实现接口,重写开车方法,通过钩爪器传入车类,调用车类方法,然后前后增强。

/**
 * 交通工具接口
 * 
 * @author CHAN
 * @date 2020/05/02
 */
public interface Vehicle {
    void drive();
}
/**
 * 车类
 * 
 * @author CHAN
 * @date 2020/05/02
 */
public class Car implements Vehicle {
    @Override
    public void drive() {
        System.out.println("开车...");
    }
}
/**
 * 日志代理类
 * 
 * @author CHAN
 * @date 2020/05/02
 */
public class LogProxy implements Vehicle{
    Vehicle vehicle;

    public LogProxy(Vehicle vehicle) {
        this.vehicle = vehicle;
    }

    @Override
    public void drive() {
        System.out.println("发动引擎...");
        vehicle.drive();
        System.out.println("关闭引擎...");
    }
}

动态代理

两种实现方式,底层通过 ASM 生成字节码文件(代理类)

JDK 动态代理

JDK 动态代理中,被代理类和代理类都需要实现同一个接口。

/**
 * 动态代理 
 */
public class App {
    public static void main(String[] args) {
        // 输出生成的代理类到指定路径
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");

        // 通过 Proxy 生成代理对象,传入被代理类(Car)和需要代理类实现的接口
        Vehicle vehicle = (Vehicle) Proxy.newProxyInstance(Car.class.getClassLoader(),
                new Class[]{Vehicle.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                        System.out.println("发动引擎...");
                        method.invoke(new Car(), objects);
                        System.out.println("关闭引擎...");
                        return o;
                    }
                });
        vehicle.drive();
    }
}

输出

发动引擎...
开车...
关闭引擎...

通过查看动态生成的代理类,可以发现,在调用 Drive() 方法时,代理类调用了 InvocationHandler 的 invoke 方法实现了增强。

public final class $Proxy0 extends Proxy implements Vehicle {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void drive() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("org.example.Vehicle").getMethod("drive");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

调用流程

CGLIB 动态代理

JDK 的动态代理是代理类必须有一个实现的接口,才能生成代理类。
而 CGLIB 则无序实现接口。

<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
  <groupId>cglib</groupId>
  <artifactId>cglib</artifactId>
  <version>3.3.0</version>
</dependency>
/**
 * cglib 动态代理
 *
 * @author CHAN
 * @date 2020/05/02
 */
public class App {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Car.class);
        // 相当于 JDK 代理中的 InvocationHandler
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("开启引擎");
                Object result = methodProxy.invokeSuper(o, objects);
                System.out.println("关闭引擎");
                return result;
            }
        });
        Car car = (Car) enhancer.create();
        car.drive();
    }
}
/**
 * 无需实现接口
 * 
 * @author CHAN
 * @date 2020/05/02
 */
public class Car {
    public void drive() {
        System.out.println("开车...");
    }
}

全部评论0