開發過程當中,會涉及到文案展現的動做。這些文案可能須要從持久化或者程序處理過程當中的內容來進行展現。最蛋疼的事情,因爲其中文案的變更性或者設計問題,致使這些文案在程序的各個位置,經過各類stringbuffer、stringbuilder甚至直接各類 "" + "" 之類的拼接,致使程序千瘡百孔,不夠「優雅」不說,後面維護的成本簡直不談了。java
其實大部分狀況下,文案若是不涉及到須要根據持久化數據活着計算的數據進行展現的話,實際上是能夠很簡單提到一個配置中心去,數據庫也罷、配置文件也罷,甚至相似zookeeper之類的中間件也均可以。可是若是須要根據某些數據實時替換裏面的內容,那就顯得費勁了。正則表達式
咱們知道Java提供了一個叫作MessageFormat的類,裏面直接format一些一些固定格式。好比咱們定義一句話叫作:滿{0}減{1}元,而後咱們傳入給你MessageFormat.format一個數組,數組的內容是:{100,10},因而咱們能夠根據MessageFormat得到文案爲:滿100減10元。數據庫
其實這個是比較簡單和易於理解的,咱們只須要在程序中把須要動態生成的內容填充到一個數組中,而後將文案配置在另一個位置,而後不停的調用MessageFormat去得到須要的文案,這樣子也能夠。然而這種作法有一個問題,就是數組的含義不明確,嚴重依賴填入順序,同時在外面配置文案的時候也並不明白那個0或者1究竟是個什麼東西。apache
既然咱們知道哪些地方該填充什麼內容,其實不如咱們整理系統全部文案,而後抽象和公用一些關鍵詞,經過約定的關鍵詞填充在文案中,與此同時,程序裏面將數組的結構轉換爲Map結構,map的key就是這些關鍵詞,value就是剛纔數組的內容了。如此咱們能夠擺脫對於數組順序的要求,同時文案的配置也能夠從開發同窗的手中轉移到PM甚至運營同窗的手中。數組
然而咱們還須要肯定這種方案的性能以及可用性,因而咱們能夠作一個實驗:緩存
import com.google.common.base.Stopwatch; import org.apache.commons.lang3.StringUtils; import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * created by @author <a href="mailto:congshaogang@meituan.com">Shaogang Cong</a> on 16/5/31. */ public class EffiencyTest { private static String aaa = "滿{sum}元減{credit}元,在線支付再減{cre1},限{start}到{endtime}"; private static String aaa1 = "滿{0}元減{1}元,在線支付再減{2},限{3}到{4}"; static Object[] aaa1Array = {100, 19, 20, "23:30", "23:45"}; static Map<String, Object> parameterMap = new HashMap<String, Object>(); static { parameterMap.put("sum", 100); parameterMap.put("credit", 19); parameterMap.put("cre1", 20); parameterMap.put("start", "23:30"); parameterMap.put("endtime", "23:45"); } public static void main(String[] args) { Stopwatch stopwatch = Stopwatch.createStarted(); for (int i = 0; i < 100000; i++) { MessageFormat.format(aaa1, aaa1Array); } System.out.println("messageformat" + stopwatch.elapsed(TimeUnit.MILLISECONDS)); String patternString = "\\{(" + StringUtils.join(parameterMap.keySet(), "|") + ")\\}"; System.out.println(patternString); stopwatch.reset(); stopwatch.start(); Pattern pattern = Pattern.compile(patternString); for (int i = 0; i < 100000; i++) { Matcher matcher = pattern.matcher(aaa); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, parameterMap.get(matcher.group(1)).toString()); } matcher.appendTail(sb); System.out.println(sb.toString()); } System.out.println("pattern" + stopwatch.elapsed(TimeUnit.MILLISECONDS)); } }
執行結果:app
messageformat910 \{(endtime|start|sum|cre1|credit)\} pattern229
咱們會發現,Map的方式不但容易理解,並且效率要遠高於messageformat的方式。同時,咱們徹底能夠作到正則表達式裏面的pattern提早compile 暫存起來,若是確實有變化,還能夠經過刷新緩存的方式進行更新。性能
最後,咱們講Map中的key統一到一個常量類活着其餘結構中,供開發、產品或者運營童鞋使用便可了。ui