Java —— 泛型&抽象工廠的設想

問題

增加對象類型需要增加對應工廠類。同時要將相應的工廠類設置到需要生成對象的模塊中。強類型綁定增加過多的類似代碼。

目標

使用泛型抽象要生成的對象,使用抽象工廠,動態化設定工廠類型。

實現

  • 默認類型
// 一個簡單的消息對象,內部類設計並不友好
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中泛型在內部進行強制類型轉換。
以抽象類直接獲得對象實例。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章