问题
增加对象类型需要增加对应工厂类。同时要将相应的工厂类设置到需要生成对象的模块中。强类型绑定增加过多的类似代码。
目标
使用泛型抽象要生成的对象,使用抽象工厂,动态化设定工厂类型。
实现
- 默认类型
// 一个简单的消息对象,内部类设计并不友好
public class DefaultPacket {
private static DefaultPacket dp = new DefaultPacket();
private int cmd;
private Content content;
private String seq;
private DefaultPacket() {
this.seq = UUID.randomUUID().toString();
}
public DefaultPacket(int cmd, Content content) {
this();
this.cmd = cmd;
this.content = content;
}
public int getCmd() {
return cmd;
}
public void setCmd(int cmd) {
this.cmd = cmd;
}
public Content getContent() {
return content;
}
public void setContent(Content content) {
this.content = content;
}
public String getSeq() {
return seq;
}
public void setSeq(String seq) {
this.seq = seq;
}
@Override
public String toString() {
return this.getClass().getName() + " [cmd=" + cmd + ", content=" + content + ", seq=" + seq + "]";
}
public static Content newContent(String msg, int status, int result, String desc) {
return dp.new Content(msg, status, result, desc);
}
public class Content {
private String msg;
private int status;
private int result;
private String desc;
public Content(String msg, int status, int result, String desc) {
super();
this.msg = msg;
this.status = status;
this.result = result;
this.desc = desc;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Content [msg=" + msg + ", status=" + status + ", result=" + result + ", desc=" + desc + "]";
}
}
}
- 带着点抽风的工厂类
public abstract class PacketFactory {
private static Map<String, PacketFactory> factorys;
// 私有构造方法,不允许直接生成对象
private PacketFactory() {
}
/**
* 构造工厂实体
* @param clazz 用于生成目标的对象类型
* @return Factory build packet with clazz type
*/
public static PacketFactory getFactory(Class<? extends DefaultPacket> clazz) {
if (factorys == null) {
factorys = new HashMap<>();
}
String name = clazz.getName();
PacketFactory factory;
// 力所能及的加个缓存
if ((factory = factorys.get(name)) == null) {
factory = new PacketFactory() {
@SuppressWarnings("unchecked")
@Override
public <T extends DefaultPacket> T getPacket(int cmd, Content content) {
DefaultPacket packet = null;
Constructor<? extends DefaultPacket> constructor = null;
try {
constructor = clazz.getConstructor(int.class, Content.class);
packet = constructor.newInstance(cmd, content);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(
String.format("%s构造方法不符合约定参数列表(int cmd,Content content)", clazz.getName()));
}
return (T) packet;
}
};
factorys.put(name, factory);
}
return factory;
}
/**
* 直接获得生成默认类型的工厂
* @return PacketFactory with defaultPacket
*/
public static PacketFactory getFactory() {
return getFactory(DefaultPacket.class);
}
/**
* 获得消息对象
* @param cmd
* @param content
* @return
*/
public abstract <T extends DefaultPacket> T getPacket(int cmd, Content content);
}
参考
mybatis中泛型在内部进行强制类型转换。
以抽象类直接获得对象实例。