zoukankan      html  css  js  c++  java
  • 模板模式(Template)

    行为型:Template(模板模式)

      作为一个曾经爱好写文章,但是不太懂得写文章的人,我必须承认,开头是个比较难的起步。

      模板模式常规定义:模板模式定义了一个算法步骤,把实现延迟到子类(这和抽象工厂是一样的,只不过模板模式强调的是算法步骤已经被定义好,我们只是开放某些算法步骤给子类去实现,以达到扩展的目的)。

     

      事实上模板模式跟策略模式会有些相像,然而策略模式是对算法的封装,而模板模式是定义好了算法的执行流程,将子流程抽象化。而之前接触过的工厂模式正是模板模式的一种特殊实现。

     

      最开始接触java的时候每个人都会从JDBC写起,如果把设置配置参数到获取数据库连接,取得数据等等的过程不断重复地编写,确实是一个让人无法忍受的事情。我们可以通过一段代码来体验一下:

     

         // 这是JDBC版本
            Class.forName("com.mysql.jdbc.Driver");
            String DB_URL = "jdbc:mysql://localhost:3306/shop";
            String USER = "root";
            String PASS = "";
            Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);
            Statement statement = connection.createStatement();
            statement.executeUpdate("");
            statement.close();
            connection.close();
    
    
            // 这是Spring JDBC模板的版本
            jdbcTemplate.update("");
            jdbcTemplate.execute("");

     

    从上面可以很明显的看出,如果是原生JDBC的话,我们将需要从注册驱动-配置参数-创建连接-执行脚本-关闭连接,几乎都是千篇一律的代码。而模板代码我们只需要调用统一的方法,其前后将会帮我们处理开启和关闭的动作。

     

    我们也可以通过ClassLoader类来理解

    由于ClassLoader需要保持Class对象的单例,所以通过一种双亲委派的机制来保证,那么如何限定扩展的人不去破坏这种双亲委派机制,又能够提供扩展性呢,这里就很适合用到模板设计模式。

    我们的扩展点只在这个方法

    /**
         * Finds the class with the specified <a href="#binary-name">binary name</a>.
         * This method should be overridden by class loader implementations that
         * follow the delegation model for loading classes, and will be invoked by
         * the {@link #loadClass loadClass} method after checking the
         * parent class loader for the requested class.
         *
         * @implSpec The default implementation throws {@code ClassNotFoundException}.
         *
         * @param   name
         *          The <a href="#binary-name">binary name</a> of the class
         *
         * @return  The resulting {@code Class} object
         *
         * @throws  ClassNotFoundException
         *          If the class could not be found
         *
         * @since  1.2
         */
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            throw new ClassNotFoundException(name);
        }

     

    以一个比较简单的例子来说明。

     

    package top.gabin.design.template;
    
    /**
     * 家政人员
     * @author linjiabin on  16/5/9
     */
    public abstract class HouseWorker {
        // 家政服务
        protected final void housekeeping() {
            cleanRoom();
            cooking();
            if (needFeedDog()) {
                feedDog();
            }
        }
        // 清理房间
        public abstract void cleanRoom();
        // 煮饭
        public abstract void cooking();
        // 喂狗
        public abstract void feedDog();
        // hook,钩子
        public boolean needFeedDog() {
            return true;
        }
    }
    package top.gabin.design.template;
    
    /**
     * 钟点工
     * @author linjiabin on  16/5/9
     */
    public class HourlyHouseWorker extends HouseWorker {
        private Integer salary;
        public void cleanRoom() {
            System.out.println("我只能打扫半小时");
        }
    
        public void cooking() {
            System.out.println("一个小时内必须把饭菜做好");
        }
    
        @Override
        public boolean needFeedDog() {
            // 钱给的够多的话,我愿意帮您喂狗
            return salary > 1000;
        }
    
        public void feedDog() {
            System.out.println("虽然我不愿意喂狗,但是如果多给钱的话,我也是可以的.");
        }
    }

    hook,钩子。通常在父类是一个默认的空实现,需要的话,子类将去实现它,或者也可以跟上面一样,只是一个返回true的方法。表示这件事并非所有的子类都必须去做。

    再次重新表述一次,家政人员需要做的事情几乎都是一样的,而我们将会对家政人员有等级的划分。不同等级的可以达到的效果不一样,但是我们又不希望家政人员额外地做别的事,因为这将是他们(家政)自己的外快(家政公司将无法收取额外服务的抽成)

     

  • 相关阅读:
    [arXiv18]更快的基于非二叉化自底向上策略的转移系统成分句法分析
    [AAAI18]面向序列建模的元多任务学习
    [COLING18]两种成分句法分析的局部特征模型
    [ACL18]基于RNN和动态规划的线性时间成分句法分析
    成分句法分析综述
    [NAACL16]RNN文法
    [TACL17]基于中序转移的成分句法分析
    K-摇臂赌博机算法与实现
    关于JVM案例分析(四)
    关于JVM案例分析(三)
  • 原文地址:https://www.cnblogs.com/gabin/p/5474947.html
Copyright © 2011-2022 走看看