工作中的設(shè)計模式 —— 原型模式

前言
原型模式是一種創(chuàng)建型設(shè)計模式, 使你能夠復(fù)制已有對象, 而又無需使代碼依賴它們所屬的類。
通俗說法,就是將一個類作為原型,然后復(fù)制出來另一個類。
1
使用場景
這么一說,是不是發(fā)現(xiàn)我們經(jīng)常使用?
比如咱們項目中有 BO、DTO、VO,但是在開發(fā)過程中,需要各種轉(zhuǎn)換,get/set,一般情況下大家都會使用 BeanUtils,將一個類的屬性值 set 到另一個類的屬性值中,然后返回。
當然,也有一個實體直接從頭捅到尾的。
關(guān)于 BeanUtils 的 copy 方法,各個框架都提供了相關(guān)工具,不過 Java 開發(fā)手冊 有指出 Apache BeanUtils 性能較差、也推薦了其他框架。

這里介紹的是使用 Cglib BeanCopier。
2
封裝工具類
查看文檔,先封裝一個工具類:
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 創(chuàng)建對象,是不是很麻煩?
所以就想到需要用緩存!
將 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)) {
// 進入到這里會創(chuàng)建一個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);
到這里,大家發(fā)現(xiàn),好像就封裝了一個工具類,和原型模式并沒有什么關(guān)系啊。
3
對象的 clone
到此其實在代碼中都可以使用了,不過還是要在 DTO、VO 中聲明 clone 方法,這樣之后使用才會更方便~
/**
* 將當前對象轉(zhuǎn)化為目標對象
*
* @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;
}
現(xiàn)在使用的時候就可以
AccountVO accountVO = accountDTO.clone(AccountVO.class);
不過也是有弊端的,比如這里使用的是泛型,我明明是 UserVO 要 Clone , 你非得傳一個 AddressDTO,那我也沒得辦法了。
至于進一步演化,可以將 clone 抽象到公共方法中,比如給所有 DTO 創(chuàng)建一個 BaseDTO。
還有深拷貝這塊,也需要注意。
4
總結(jié)
其實工作中有很多設(shè)計模式,只不過用到了,大家沒有發(fā)現(xiàn)。
當然工作中使用的時候,都是一切為了敏捷,可能并沒有定義什么 Prototype 接口之類的,但是還是要多總結(jié)。
最后,小伙伴們工作中,有使用什么設(shè)計模式,以及實際中的應(yīng)用場景,歡迎留言分享。
相關(guān)資料
- <End /> -
歷史文章 | 相關(guān)推薦

