美文网首页
论模板模式

论模板模式

作者: 行走的鸡汤哥 | 来源:发表于2019-04-06 00:26 被阅读0次

    模板方法模式的实现方案比对

    问题:模板方法模式的主要意义在于规范算法流程。标准的模板方法模式采用抽象类的实现方案。但规范流程更像是规范行为。而抽象类与接口相比,抽象类侧重于属性,接口侧重于行为。再者java8开始,接口中可以编写默认方法,因此模板方法模式可以采用抽象类和接口两种实现方案。那么到底哪种实现方案比较合适呢?

    需求:按指定流程推送数据。流程如下:
    从数据库中查询数据 ---> 封装数据 ---> 推送

    标准模板方法模式的写法

    抽象模板类(抽象类):规范数据的使用流程

    /**
     * Created by r.x on 2019/4/5.
     * 抽象模板
     */
    public abstract class Template<T> {
    
        /**
         * 数据使用流程:
         * 1、查库
         * 2、封装数据
         * 3、推送数据
         */
        public final void use() {
            List<T> list = queryDb();
            JSONObject json = packData(list);
            push(json);
        }
    
        /**
         * 从数据库查询数据
         *
         * @return
         */
        protected abstract List<T> queryDb();
    
        /**
         * 按要求 封装数据
         *
         * @param list
         * @return
         */
        protected abstract JSONObject packData(List<T> list);
    
        /**
         * 通用的数据推送方法
         * @param json
         */
        private void push(JSONObject json) {
            System.out.println(json);
        }
    }
    

    string的具体使用实现

    /**
     * Created by r.x on 2019/4/5.
     * string的具体使用实现
     */
    public class PushString extends Template<String> {
    
        @Override
        protected List<String> queryDb() {
            return Collections.singletonList("string");
        }
    
        @Override
        protected JSONObject packData(List<String> list) {
            StringJoiner joiner = new StringJoiner(",");
            list.forEach(joiner::add);
            JSONObject json = new JSONObject();
            json.put("type", "string");
            json.put("data", joiner.toString());
            return json;
        }
    }
    

    integer的具体使用实现

    /**
     * Created by r.x on 2019/4/5.
     * integer的具体使用实现
     */
    public class PushInteger extends Template<Integer> {
    
        @Override
        protected List<Integer> queryDb() {
            return Collections.singletonList(0);
        }
    
        @Override
        protected JSONObject packData(List<Integer> list) {
            JSONObject json = new JSONObject();
            json.put("type", "integer");
            json.put("data", list);
            return json;
        }
    }
    

    入口类:

    /**
     * Created by r.x on 2019/4/5.
     * 入口类
     */
    public class Demo {
    
        public static void main(String[] args) {
            Template<String> pushString = new PushString();
            pushString.use();
    
            Template<Integer> pushInteger = new PushInteger();
            pushInteger.use();
        }
    }
    

    输出结果

    {"data":"string","type":"string"}
    {"data":[0],"type":"integer"}
    

    用接口的方式实现模板方法模式

    抽象模板(接口)

    /**
     * Created by r.x on 2019/4/5.
     * 抽象模板
     */
    public interface ITemplate<T> {
        /**
         * 数据使用流程:
         * 1、查库
         * 2、封装数据
         * 3、推送数据
         */
        default void use() {
            List<T> list = queryDb();
            JSONObject json = packData(list);
            push(json);
        }
    
        /**
         * 从数据库查询数据
         *
         * @return
         */
        List<T> queryDb();
    
        /**
         * 按要求 封装数据
         *
         * @param list
         * @return
         */
        JSONObject packData(List<T> list);
    
        /**
         * 通用的数据推送方法
         * @param json
         */
        default void push(JSONObject json) {
            System.out.println(json);
        }
    }
    

    integer的具体使用实现

    /**
     * Created by r.x on 2019/4/5.
     * integer的具体使用实现
     */
    public class PushIntegerImpl implements ITemplate<Integer> {
    
        @Override
        public List<Integer> queryDb() {
            return Collections.singletonList(-1);
        }
    
        @Override
        public JSONObject packData(List<Integer> list) {
            JSONObject json = new JSONObject();
            json.put("type", "integer impl");
            json.put("data", list);
            return json;
        }
    }
    

    string的具体使用实现

    /**
     * Created by r.x on 2019/4/6.
     * string的具体使用实现
     */
    public class PushStringImpl implements ITemplate<String> {
        @Override
        public List<String> queryDb() {
            return Collections.singletonList("string impl");
        }
    
        @Override
        public JSONObject packData(List<String> list) {
            StringJoiner joiner = new StringJoiner(",");
            list.forEach(joiner::add);
            JSONObject json = new JSONObject();
            json.put("type", "string impl");
            json.put("data", joiner.toString());
            return json;
        }
    }
    

    入口类

    /**
     * Created by r.x on 2019/4/5.
     * 入口类
     */
    public class DemoImpl {
    
        public static void main(String[] args) {
            ITemplate<String> pushString = new PushStringImpl();
            pushString.use();
    
            ITemplate<Integer> pushInteger = new PushIntegerImpl();
            pushInteger.use();
        }
    }
    

    输出结果:

    {"data":"string impl","type":"string impl"}
    {"data":[-1],"type":"integer impl"}
    

    那么从输出结果可以看出,采用接口的方式也是可以实现同样的效果的

    抽象类与接口方案的比对

    从以上对比可以看出,虽然接口方式也能实现模板方法模式,但接口中定义的方法完全暴露了,甚至连最重要的use()方法也被暴露了,因为子类可以覆盖接口中的默认方法,此时就失去了规范流程的意义了。因此,即使技术上可行,但也不推荐使用接口的实现方案。

    相关文章

      网友评论

          本文标题:论模板模式

          本文链接:https://www.haomeiwen.com/subject/gjlxiqtx.html