前言

原型模式是一种创立型设计模式, 使你可能复制已有对象, 而又无需使代码依赖它们所属的类。

艰深说法,就是将一个类作为原型,而后复制进去另一个类。

应用场景

这么一说,是不是发现咱们常常应用?

比方咱们我的项目中有 BO、DTO、VO,然而在开发过程中,须要各种转换,get/set,个别状况下大家都会应用 BeanUtils,将一个类的属性值 set 到另一个类的属性值中,而后返回。

当然,也有一个实体间接从头捅到尾的。

对于 BeanUtils 的 copy 办法,各个框架都提供了相干工具,不过 Java 开发手册 有指出 Apache BeanUtils 性能较差、也举荐了其余框架。

这里介绍的是应用 Cglib BeanCopier。

封装工具类

查看文档,先封装一个工具类:

public class BeanCopierUtils {    private BeanCopierUtils() {    }    /**     * 将source对象的属性拷贝到target对象中去     *     * @param source source对象     * @param target target对象     */    public static void copyProperties(Object source, Object target) {        BeanCopier beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);        beanCopier.copy(source, target, null);    }}

看到这里是不是感觉,如果我应用 BeanCopier 比拟频繁,而后每次都 create 创建对象,是不是很麻烦?

所以就想到须要用缓存!

将 BeanCopier 作为一个,在各个线程应用的时候,共享。

public class BeanCopierUtils {    private BeanCopierUtils() {    }    /**     * BeanCopier缓存     */    private static Map<String, BeanCopier> CACHE = new HashMap<>();    /**     * 将source对象的属性拷贝到target对象中去     *     * @param source source对象     * @param target target对象     */    public static void copyProperties(Object source, Object target) {        String cacheKey = source.getClass().getName() + target.getClass().getName();        BeanCopier beanCopier;        if (!CACHE.containsKey(cacheKey)) {            // 进入到这里会创立一个BeanCopier实例并且放在缓存map中            beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);            CACHE.put(cacheKey, beanCopier);        } else {            beanCopier = CACHE.get(cacheKey);        }        beanCopier.copy(source, target, null);    }}

而后再代码中就能够欢快的应用啦!

BeanCopierUtils.copyProperties(dto, vo);

到这里,大家发现,如同就封装了一个工具类,和原型模式并没有什么关系啊。

对象的 clone

到此其实在代码中都能够应用了,不过还是要在 DTO、VO 中申明 clone 办法,这样之后应用才会更不便~

/** * 将以后对象转化为指标对象 * * @param clazz * @param <T> * @return * @throws Exception */public <T> T clone(Class<T> clazz) throws Exception {    T target = clazz.newInstance();    BeanCopierUtils.copyProperties(this, target);    return target;}

当初应用的时候就能够

AccountVO accountVO = accountDTO.clone(AccountVO.class);

不过也是有弊病的,比方这里应用的是泛型,我明明是 UserVO 要 Clone , 你非得传一个 AddressDTO,那我也没得方法了。

至于进一步演变,能够将 clone 形象到公共办法中,比方给所有 DTO 创立一个 BaseDTO。

还有深拷贝这块,也须要留神。

总结

其实工作中有很多设计模式,只不过用到了,大家没有发现。

当然工作中应用的时候,都是所有为了麻利,可能并没有定义什么 Prototype 接口之类的,然而还是要多总结。

最初,小伙伴们工作中,有应用什么设计模式,以及理论中的利用场景,欢送留言分享。

相干材料

  1. 《深刻设计模式》:https://refactoringguru.cn/design-patterns
  2. 封面图:https://refactoringguru.cn/design-patterns/prototype