上一篇blog中將工具類寫成了靜態類(全部的方法都是靜態方法),今天發現了這種方式的弊端。且聽我慢慢道來:java
今天須要重構一個實習生的代碼,邏輯很簡單,消費kafka,提取須要的內容寫入ssdb,他將配置信息直接寫到了項目中,而咱們須要區分本地、測試、生產環境,不現實,這就是重構的緣由。redis
這就要求我必須封裝kafka消費、jedis(ssdb兼容jedis)讀寫工具類。原本打算照着前幾天的作,可是想着參照參照大牛的代碼,學習學習提高本身。spring
打開大牛的代碼,發現全部相似的工具類都是非靜態的,而是spring注入(默認是單例模式)那麼問題來了:工具類用單例模式仍是靜態類好?ide
因而又是上網搜,最後經過知乎、博客等途徑,主要了解了一下區別:工具
說靜態類好的:學習
說單例好的:測試
所以,我得出如下結論:this
Math.abs()
,若是寫個單例,可能全世界都要笑話你了。下面貼一個有配置信息的工具類,並以此分析:code
代碼1server
public interface JedisResourceFactory { public Jedis getResource(); }
代碼2
public class JedisPoolResourceFactory implements JedisResourceFactory, DisposableBean { private static final int DEFAULT_PORT = 3306; private JedisPoolConfig jedisPoolConfig; private String host; private int port; private JedisPool jedisPool; public JedisPoolResourceFactory(JedisPoolConfig jedisPoolConfig, String host) { this(jedisPoolConfig, host, DEFAULT_PORT); } public JedisPoolResourceFactory(JedisPoolConfig jedisPoolConfig, String host, int port) { this.jedisPoolConfig = jedisPoolConfig; this.host = host; this.port = port; init(); } private void init() { this.jedisPool = new JedisPool(this.jedisPoolConfig, this.host, this.port); } @Override public Jedis getResource() { return jedisPool.getResource(); } @Override public void destroy() throws Exception { jedisPool.close(); } }
代碼3
public class JedisServer { JedisResourceFactory jedisResourceFactory; public JedisServer(JedisResourceFactory jedisResourceFactory) { this.jedisResourceFactory = jedisResourceFactory; } abstract class Executor<T> { Jedis jedis; public Executor(JedisResourceFactory jedisResourceFactory) { this.jedis = jedisResourceFactory.getResource(); } abstract T execute(); public T getResult() { T result = null; try { result = execute(); } catch (Exception e) { throw new RuntimeException("Redis execute Error", e); } finally { if (jedis != null) { jedis.close(); jedis = null; } } return result; } } public Long lpushStrings(final String key, final String[] values) { return new Executor<Long>(jedisResourceFactory) { @Override Long execute() { return jedis.lpush(key, values); } }.getResult(); } }
首先上面這3段代碼爲了訪問redis,先經過redisPool獲取redis,而後訪問redis。(以上工具類僅用來訪問單機redis,redis集羣須要經過其餘方式)
假如咱們如今有一個redis源,那麼實例化一個JedisPoolResourceFactory對象factory1,而後實例化一個JedisServer的對象jserver1。
又一天咱們多了一個redis源,一樣再實例化一個JedisPoolResourceFactory對象factory2,而後實例化一個JedisServer的對象jserver2。這樣咱們就能夠輕鬆的經過不一樣的對象訪問不一樣的redis。
若是使用靜態的工具類,難道CV(ctrl c , ctrl v)大法複製多個工具類出來嗎?