相关阅读:java
JAVA基础(一)简单、透彻理解内部类和静态内部类
JAVA基础(二)内存优化-使用Java引用作缓存
JAVA基础(三)ClassLoader实现热加载
JAVA基础(五)函数式接口-复用,解耦之利刃
JAVA编程思想(一)经过依赖注入增长扩展性
JAVA编程思想(二)如何面向接口编程
JAVA编程思想(三)去掉别扭的if,自注册策略模式优雅知足开闭原则
JAVA编程思想(四)Builder模式经典范式以及和工厂模式如何选?
HikariPool源码(二)设计思想借鉴
人在职场(一)IT大厂生存法则编程
枚举能够用来定义常量,也能够看成工厂类使用,其相比常量定义,定义能够更集中;相比工厂类,表达is A(某一种类型)的语义更强。缓存
class Constants {
// 常量定义方式通常经过相同前缀来分类,只要保证定义在同一个代码段就没问题,若是分散到多个代码段,找起来就挺费劲
public static final int SERV_TYPE_CAR = 1;
public static final int SERV_TYPE_TV = 2;
public static final int SERV_TYPE_MOBILE = 3;
// 经过枚举定义的方式更加集中,不可能会分散到多个代码段
public enum SERV_TYPE {
CAR, TV, MOBILE
}
}
复制代码
// 使用常量
public static void dox(int servType) {
switch (servType) {
case Constants.SERV_TYPE_CAR:
// do something
break;
case Constants.SERV_TYPE_MOBILE:
// do something
break;
case Constants.SERV_TYPE_TV:
// do something
break;
default:
break;
}
}
// 使用枚举
public static void doy(Constants.SERV_TYPE servType) {
switch (servType) {
case CAR:
// do something
break;
case TV:
// do something
break;
case MOBILE:
// do something
break;
default:
break;
}
}
复制代码
可见,在使用上无多大区别,枚举的好处是在定义时更加集中,好维护,同时还限定了入参的取值范围,使得更不容易发生参数输入错误的状况。ide
枚举充当工厂类的用法在不少开源项目中均可以看到,其做用和工厂类同样。先看下例子的类结构:函数
类 | 职责 |
---|---|
CacheType | 缓存类型,枚举类,经过它来获取对应的缓存类实例 |
BasicCache | 缓存类接口,对外暴露 |
ConcurrentMapCache | ConcurrentMap实现的缓存,能够不对外暴露 |
LinkedHashMapCache | LinkedHashMap实现的缓存,能够不对外暴露 |
public interface BasicCache<K, V> {
V get(K key);
void put(K key, V value);
}
复制代码
// 注:没有public修饰,只在包内访问,屏蔽了可见性,对外只暴露BasicCache
final class LinkedHashMapCache<K, V> implements BasicCache<K, V> {
private final Map<K, V> map;
public LinkedHashMapCache(int maximumSize, boolean accessOrder) {
map = new BoundedLinkedHashMap<>(maximumSize, accessOrder);
}
@Override
public V get(K key) {
synchronized (map) {
return map.get(key);
}
}
@Override
public void put(K key, V value) {
synchronized (map) {
map.put(key, value);
}
}
static final class BoundedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L;
private final int maximumSize;
public BoundedLinkedHashMap(int maximumSize, boolean accessOrder) {
super(maximumSize, 0.75f, accessOrder);
this.maximumSize = maximumSize;
}
@Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maximumSize;
}
}
}
final class ConcurrentMapCache<K, V> implements BasicCache<K, V> {
private final ConcurrentMap<K, V> map;
public ConcurrentMapCache(ConcurrentMap<K, V> map) {
this.map = requireNonNull(map);
}
@Override
public V get(K key) {
return map.get(key);
}
@Override
public void put(K key, V value) {
map.put(key, value);
}
}
复制代码
public enum CacheType {
ConcurrentHashMap {
@Override public <K, V> BasicCache<K, V> create(int maximumSize) {
return new ConcurrentMapCache<>(new ConcurrentHashMap<>(maximumSize));
}
},
LinkedHashMap {
@Override public <K, V> BasicCache<K, V> create(int maximumSize) {
return new LinkedHashMapCache<>(maximumSize, true);
}
};
public abstract <K, V> BasicCache<K, V> create(int maximumSize);
}
复制代码
// 使用枚举,可充当工厂类做用
BasicCache<String, String> enumConcurrentHash = CacheType.ConcurrentHashMap.create(2);
BasicCache<String, String> enumLinkedHash = CacheType.LinkedHashMap.create(2);
复制代码
能够看到,此时枚举类充当了工厂类的做用。post
若是ConcurrentMapCache和LinkedHashMapCache定义为public的,那么能够直接实例化,以下:优化
BasicCache<String, String> concurrentMapCache = new ConcurrentMapCache<>(new ConcurrentHashMap<>(2));
BasicCache<String, String> linkedHashMapCache = new LinkedHashMapCache<>(2, true);
复制代码
既然能够直接实例化,为何还须要经过枚举来建立实例? 其主要目的和工厂类同样:屏蔽建立类实例的逻辑,外部直接使用接口就好。ui
// 工厂类
public final class CacheFactory {
public static BasicCache createConcurrentMapCache(int maximumSize) {
return new ConcurrentMapCache<>(new ConcurrentHashMap<>(maximumSize));
}
public static BasicCache createLinkedHashMapCache(int maximumSize) {
return new LinkedHashMapCache<>(maximumSize, true);
}
}
// 使用
BasicCache<String, String> concurrentHashCache = CacheFactory.createConcurrentMapCache(2);
BasicCache<String, String> linkedHashCache = CacheFactory.createLinkedHashMapCache(2);
复制代码
从以上例子类看,枚举和工厂类用法并无多大区别.this
- 在做为常量定义使用时,枚举和常量定义差异不大,只是定义更加集中,方便维护。
- 在做为建立工厂使用时,枚举和工厂类没啥差异,只是业务语义稍有不一样,枚举的is A语义更强,能够先表达is A而后再建立具体类实例,而工厂类是一步到位建立具体类实例。
- 工厂和直接new实例的区别是,工厂能够屏蔽建立实例的细节,只暴露实例的接口,尤为在建立复杂实例时,工厂的优点比经过new来建立类实例大得多。
- 可见,以上差异不是很大,具体使用时不须要太纠结,不必争个孰优孰劣。
end.spa