
commons.box.app.SObjectFactory Maven / Gradle / Ivy
Show all versions of commons-box-app Show documentation
package commons.box.app;
import commons.box.app.func.DataFunction;
import commons.box.util.Collects;
import commons.box.util.Logs;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 单例模式对象工厂
*/
public class SObjectFactory {
private static final AppLog LOG = Logs.get(SObjectFactory.class);
protected final Map> objects = new SafeMap<>();
public SObjectFactory() {
}
protected SObjectFactory(Map> objects) {
if (objects != null) this.objects.putAll(objects);
}
/**
* 是否包含对象
*
* @param name
* @return
*/
public boolean has(K name) {
if (name == null) return false;
return this.objects.containsKey(name);
}
public Set names() {
return Collects.immset(this.objects.keySet());
}
public List values() {
List values = new ArrayList<>();
for (SObject vo : this.objects.values()) if (vo != null && vo.raw() != null) values.add(vo.raw());
return Collects.immlist(values);
}
/**
* 增加provider
*
* @param name
* @param provider
*/
public void provider(K name, DataFunction provider) {
if (name == null) return;
synchronized (this.objects) {
if (provider == null) this.objects.remove(name);
else {
SObject sno = new SObject<>(() -> provider.apply(name));
//TODO 当前逻辑是直接替换已有声明,考虑是否需要迁移原有值
//SObject so = this.objects.get(name);
//if (so != null && so.raw() != null) sno.set(so.raw());
this.objects.put(name, sno);
}
}
}
public void add(K name, V object, boolean overwrite) {
if (name == null || object == null) return;
synchronized (this.objects) { // TODO 验证此处保持同步是否影响性能
SObject so = this.objects.get(name);
if (so == null) {
so = new SObject<>(object);
this.objects.put(name, so);
} else if (overwrite) so.set(object);
}
}
/**
* 直接获取内部对象 不存在时直接返回空
*
* @param name
* @param
* @return
*/
@SuppressWarnings("unchecked")
public T raw(final K name) {
SObject ov = this.objects.get(name);
if (ov == null) return null;
return (T) ov.raw();
}
/**
* 获取单例对象 指定对象类型 如果对象不存在则使用给定的provider获取目标对象
*
* @param name
* @param type
* @param provider
* @return
*/
public T get(final K name, final Class type, final DataFunction provider) {
T obj = this.innerGet(name, provider);
if (obj == null) return null;
if (type != null) {
if (type.isInstance(obj)) return obj;
throw new ClassCastException("生成的对象不兼容类型 " + type.getName());
}
return obj;
}
public T get(final K name, final Class type) {
return this.get(name, type, null);
}
/**
* 获取单例对象 如果对象不存在则使用给定的provider获取目标对象
*
* @param name
* @param provider
* @return
*/
public T get(final K name, final DataFunction provider) {
return this.innerGet(name, provider);
}
/**
* 为了避免 lambda 非静态引用,本方法提供了一个机制:通过 context 注入参数计算 key 和对应的 provider
*
* 注意,当 provider 引用了 context 时,需确保 context-keyFunc-provider 对于相同 keyFunc 返回值应返回相同的 provider 结果
*
* 本方法使用时,keyFunc / provider 应该是statless的(不应引用额外的外部变量和字段)。
*
* @param context
* @param keyFunc
* @param provider
* @param
* @param
* @return
*/
public final T doGet(final C context, DataFunction keyFunc, DataFunction provider) {
if (keyFunc == null) return null;
return innerDoGet(context, keyFunc.apply(context), provider);
}
/**
* 载入单例对象
*
* @param name
* @param provider
* @return
*/
private T innerGet(K name, DataFunction provider) {
if (name == null) return null;
return innerDoGet(name, name, provider);
}
@SuppressWarnings("unchecked")
private T innerDoGet(final C context, K name, DataFunction provider) {
if (name == null) return null;
SObject obj = this.objects.get(name);
if (obj == null) {
synchronized (this.objects) {
obj = this.objects.get(name);
if (obj == null) {
obj = new SObject<>(() -> (provider != null) ? provider.apply(context) : null);
this.objects.put(name, obj);
}
}
}
return (T) obj.get();
}
/**
* 获取单例对象 如果定义了name对应的provider则使用它构造对象并返回
*
* 如果provider未定义,返回空
*
* @param name
* @return
*/
public Object get(K name) {
return this.get(name, null, null);
}
public void clearObjects() {
this.objects.forEach((k, v) -> v.clear());
}
public void clear() {
this.objects.clear();
}
/**
* 单例模式对象工厂 (实现了序列化机制)
*/
public static class SerialFactory extends SObjectFactory implements Serializable {
/**
* 获取实例
*
* @return
*/
public static SerialFactory
inst() {
return new SerialFactory<>();
}
public SerialFactory() {
super();
}
private SerialFactory(Map> objects) {
super(objects);
}
private Object readResolve() {
return new SerialFactory<>(this.objects);
}
}
}