上一篇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)大法复制多个工具类出来吗?