2-2设计模式之工厂和代理模式

本文深入探讨工厂模式和代理模式在软件设计中的应用。工厂模式包括简单工厂、工厂方法和抽象工厂,能有效降低程序耦合性,提高代码可维护性。代理模式则通过代理对象控制对真实对象的访问,广泛应用于AOP、事务处理和远程调用等场景。
摘要由CSDN通过智能技术生成

工厂模式

 实现了创建者和调用者分离,工厂模式分为简单工厂、工厂方法、抽象工厂模式。

工厂模式好处

利用工厂模式可以降低程序的耦合性,为后期的维护修改提供了很大的便利。

将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦。

工厂模式分类

简单工厂模式

简单工厂模式相当于是一个工厂中有各种产品,创建在一个类中,客户无需知道具体产品的名称,只需要知道产品类所对应的参数即可。但是工厂的职责过重,而且当类型过多时不利于系统的扩展维护。

public interface Car {

public void run();

}

 

public class AoDi implements Car {

public void run() {

System.out.println("我是奥迪汽车..");

}

}

public class JiLi implements Car {

 

public void run() {

System.out.println("我是吉利汽车...");

}

}

public class CarFactory {

 

 public static Car createCar(String name) {

if (StringUtils.isEmpty(name)) {

             return null;

}

if(name.equals("奥迪")){

return new AoDi();

}

if(name.equals("吉利")){

return new JiLi();

}

return null;

}

}

public class Client01 {

 

public static void main(String[] args) {

Car aodi  =CarFactory.createCar("奥迪");

Car jili  =CarFactory.createCar("吉利");

aodi.run();

jili.run();

}

 

}

优点:简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。

缺点:很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则

工厂方法模式

工厂方法模式Factory Method,又称多态性工厂模式。在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

public interface Car {

public void run();

}

 

public class AoDi implements Car {

public void run() {

System.out.println("我是奥迪汽车..");

}

}

public class JiLi implements Car {

 

public void run() {

System.out.println("我是吉利汽车...");

}

}

public class JiLiFactory implements CarFactory {

 

public Car createCar() {

 

return new JiLi();

}

 

}

public class AoDiFactory implements CarFactory {

 

public Car createCar() {

 

return new AoDi();

}

}

public class Client {

 

public static void main(String[] args) {

Car aodi = new AoDiFactory().createCar();

Car jili = new JiLiFactory().createCar();

aodi.run();

jili.run();

}

 

}

抽象工厂模式

抽象工厂简单地说是工厂的工厂,抽象工厂可以创建具体工厂,由具体工厂来产生具体产品。

 

案例:

//发动机

public interface Engine {

 

void run();

 

void start();

}

 

class EngineA implements Engine {

 

public void run() {

      System.out.println("转的快!");

}

 

public void start() {

 System.out.println("启动快,自动档");

}

 

}

 

class EngineB implements Engine {

 

public void run() {

      System.out.println("转的慢!");

}

 

public void start() {

 System.out.println("启动快,手动档");

}

 

}

 

//座椅

public interface Chair {

   void run();

}

 

 class ChairA implements Chair{

 

public void run() {

System.out.println("可以自动加热!");

}

 

}

 class ChairB implements Chair{

 

public void run() {

System.out.println("不能加热!");

}

 

}

public interface CarFactory {

// 创建发动机

Engine createEngine();

// 创建座椅

Chair createChair();

}

public class JiLiFactory implements CarFactory  {

 

public Engine createEngine() {

 

return new EngineA();

}

 

public Chair createChair() {

 

return new ChairA();

}

 

}

public class Client002 {

 

 public static void main(String[] args) {

CarFactory carFactory=new JiLiFactory();

Engine engine=carFactory.createEngine();

engine.run();

engine.start();

 

}

 

}

简单工厂、工厂方法、抽象工厂之小结、区别

简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)

工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)

抽象工厂 :用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)

 

代理模式

通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用处理,或调用后处理。既(AOP微实现)  ,AOP核心技术面向切面编程。

代理模式应用场景

SpringAOP、事物原理、日志打印、权限控制、远程调用、安全代理 可以隐蔽真实角色

代理分类

静态代理(静态定义代理类)

动态代理(动态生成代理类)

Jdk自带动态代理

Cglib 、javaassist(字节码操作库)

 

静态代理

什么是静态代理

由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。

静态代理代码

public interface IUserDao {

void save();

}

public class UserDao implements IUserDao {

public void save() {

System.out.println("已经保存数据...");

}

}

代理类

public class UserDaoProxy implements IUserDao {

private IUserDao target;

 

public UserDaoProxy(IUserDao iuserDao) {

this.target = iuserDao;

}

 

public void save() {

System.out.println("开启事物...");

target.save();

System.out.println("关闭事物...");

}

 

}

 

JDK动态代理

1)原理:是根据类加载器和接口创建代理类(此代理类是接口的实现类,所以必须使用接口 面向接口生成代理,位于java.lang.reflect包下)

2)实现方式:

1. 通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);

2. 通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});

3. 通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});

4. 通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));

缺点:jdk动态代理,必须是面向接口,目标业务类必须实现接口

// 每次生成动态代理类对象时,实现了InvocationHandler接口的调用处理器对象

 

public class InvocationHandlerImpl implements InvocationHandler {

private Object target;// 这其实业务实现类对象,用来调用具体的业务方法

// 通过构造函数传入目标对象

public InvocationHandlerImpl(Object target) {

this.target = target;

}

 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

Object result = null;

System.out.println("调用开始处理");

result = method.invoke(target, args);

System.out.println("调用结束处理");

return result;

}

 

public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException,

IllegalAccessException, IllegalArgumentException, InvocationTargetException {

// 被代理对象

IUserDao userDao = new UserDao();

InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDao);

ClassLoader loader = userDao.getClass().getClassLoader();

Class<?>[] interfaces = userDao.getClass().getInterfaces();

// 主要装载器、一组接口及调用处理动态代理实例

IUserDao newProxyInstance = (IUserDao) Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl);

newProxyInstance.save();

}

 

}

 

CGLIB动态代理

原理:利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。 

什么是CGLIB动态代理

使用cglib[Code Generation Library]实现动态代理,并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码

CGLIB动态代理相关代码

public class CglibProxy implements MethodInterceptor {

private Object targetObject;

// 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理

public Object getInstance(Object target) {

// 设置需要创建子类的类

this.targetObject = target;

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(target.getClass());

enhancer.setCallback(this);

return enhancer.create();

}

 

public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

System.out.println("开启事物");

Object result = proxy.invoke(targetObject, args);

System.out.println("关闭事物");

// 返回代理对象

return result;

}

public static void main(String[] args) {

CglibProxy cglibProxy = new CglibProxy();

UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDao());

userDao.save();

}

}

 

CGLIB动态代理与JDK动态区别

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

Spring中。

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP

2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。
因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值