我在京东使用工厂模式,一文说清楚工厂模式

概述

在开发中工厂模式使用的非常频繁,无非就是无外乎是对象的创建,但是在实践中我们如何使用的比较多…

首先我们要分清楚工厂类和工厂要创建的类,工厂要创建的类,我们平时该怎么定义还是怎么定义,不管是什么工厂模式,都不会影响这一步相关内容,

我们平时往往喜欢使用一个简单的类,单在开发中类的结构是非常复杂的,因此我们不关心类的结构我们只关心工厂相关的实现:
在这里插入图片描述
说白了,我们今天就是探讨的红框中的实现,是如何来实现,平时我们听到的名称:
简单工厂,工厂方法, 抽象工厂等等,不管那种模式,一定存在右边的工厂类,往往存在一个顶端接口XXXFactory,并且里面只有一个方法,就是创建对象的方法

  1. 简单工厂就是分别实现XXXFactory ,开多个工厂类,在使用的过程中进行创建不同的工厂类,这个写法确实简单,
  2. 上面的方法好理解,但是在开发中使用的比较少, 代码重复太多,我们今天说说几个常用的方式

使用反射

这种方式一般在开发框架中使用比较多,业务代码开发中使用较少, 也就是说我们一个类的体系非常庞大,里面的属性又非常多,继承关系好几层,每一层针对不同的属性进行赋值,要么靠传入的数据,如果没有传入就进行默认赋值

工厂接口

public interface MyCarFactory<T extends Car> {
    /**
     * Creates a new channel.
     */
    T newCar();
}

工厂实现类

package com.factory.reflect;

import io.netty.channel.ChannelException;
import io.netty.channel.ReflectiveChannelFactory;
import io.netty.util.internal.StringUtil;

import java.lang.reflect.Constructor;
import java.util.Objects;

/**
 * @author wufagang
 * @description
 * @date 2022年07月16日 15:58
 */
public class ReflectiveCarFactory<T extends Car> implements MyCarFactory<T> {
    private final Constructor<? extends T> constructor;

    public ReflectiveCarFactory(Class<? extends T> clazz) {
        assert Objects.nonNull(clazz);
        try {
            this.constructor = clazz.getConstructor();
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) +
                    " does not have a public non-arg constructor", e);
        }
    }

    @Override
    public T newCar() {
        try {
            return constructor.newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
        }
    }

    @Override
    public String toString() {
        return StringUtil.simpleClassName(ReflectiveChannelFactory.class) +
                '(' + StringUtil.simpleClassName(constructor.getDeclaringClass()) + ".class)";
    }
}

至于car相关的类结构可以随便进行定义了,可以是很多层
这里就不在赘述了,自己随便定义就可以

创建对象:

public static void main(String[] args) {
        ReflectiveCarFactory<BCcar> bCcarReflectiveCarFactory = new ReflectiveCarFactory<>(BCcar.class);
        BCcar bCcar = bCcarReflectiveCarFactory.newCar();
        bCcar.run();


        ReflectiveCarFactory<AudiCar> audiCarReflectiveCarFactory = new ReflectiveCarFactory<>(AudiCar.class);
        AudiCar audiCar = audiCarReflectiveCarFactory.newCar();
        audiCar.run();
    }

自定义注解的方式

这种方式我经常在业务代码中使用
比如消费一个mq里面数据类型有很多中,如果一般人写代码就是一个方法入口,一串代码进行下去,稍微好点的 多写一下方法,说白了就是一个面向过程的开发,后期代码维护的时候太费劲了,代码可读性性太差直接上干货:

使用的入口

简单吧一行代码, 我们写代码尽可能达到这样的比较

MatrixInfoAnalyerFactory.allHandlerdoHandler(context);

这个类是关键所在,实现思路就是,根据自定义注解,获取所有的处理器,放入map中,
当调用上面那一行代码,就遍历map,让所有的方法执行

package com.jd.viewworld.service.cjg.matrixinfo;

import com.google.common.base.Preconditions;
import com.jd.exception.common.ComponentBusinessException;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author wufagang
 * @date 2022年05月30日 14:39
 */
@Component
public class MatrixInfoAnalyerFactory  implements ApplicationContextAware, InitializingBean {

    private static ApplicationContext context;
    private static final Map<String, MatrixInfoHandler> handlers = new HashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        String[] names = context.getBeanNamesForAnnotation(MatrixInfoAnalyer.class);
        if(ArrayUtils.isEmpty(names)){
            throw new ComponentBusinessException("消息处理器为空");
        }
        for (String name: names) {
            Object obj = context.getBean(name);
            if(!(obj instanceof MatrixInfoHandler)){
                continue;
            }
            MatrixInfoHandler bean = (MatrixInfoHandler) obj;
            MatrixInfoAnalyer annotation = AnnotationUtils.findAnnotation(bean.getClass(), MatrixInfoAnalyer.class);
            Preconditions.checkArgument(Objects.nonNull(annotation),"处理器未添加annotation!");
            String value = annotation.value();
            Preconditions.checkArgument(StringUtils.isNotBlank(value),"处理器未添加value");
            //这里不判断重复,如果编写多个相同的,使用最后加载的
            handlers.put(value,bean);
        }
    }

    public static void allHandlerdoHandler(MatrixInfoContext context){
        if(handlers.isEmpty()){
            return;
        }
        Collection<MatrixInfoHandler> handlerImpl = handlers.values();
        handlerImpl.forEach(item->{
            item.doHandler(context);
        });
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }


}

自定义注解:
如果这些handler有顺序要求,我们可以在注解中增加顺序熟悉

package com.jd.viewworld.service.cjg.matrixinfo;

import org.springframework.stereotype.Component;

import java.lang.annotation.*;


@Documented
@Component
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MatrixInfoAnalyer {

    String value() default "";
}


handler的定义和实现,这里面写自己的业务代码

public interface MatrixInfoHandler {

    void doHandler(MatrixInfoContext context);
}
@MatrixInfoAnalyer("appExtHandler")
public class AppExtHandler extends AbstractmatrixInfoHandler {
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值