zoukankan      html  css  js  c++  java
  • 设计模式之模板方法

    一、模板方法模式(封装算法)定义:

            模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

          钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类进行决定。
    子类可以覆盖钩子方法,但是也可以什么也不做,这些都是由子类自己进行决定,我们应该保持抽象方法的数目越少越好,否则,在子类中实现这些方法将会很麻烦。在写模板方法的时候,心里一定要随时记得这一点,想要做到这一点,可以让算法内的步骤不要切割的太细,但是如果步骤太少的话,会比较没有弹性,所以要视具体情况而定,此外也要记住这一点,某些步骤是可选的,所以你可以将这些步骤实现成钩子,而不是实现成抽象方法,这样就可以让抽象类的子类的负荷减轻。

    二、模板方法类图

    问题1:当你创建一个模板方法时,怎么才能知道什么时候该使用抽象方法,什么时候使用钩子?
    解答:当你的子类对于某个方法或者步骤的实现,是依赖与自身特性相关的,就必须使用抽象方法。如果方法或者步骤是可选的,那就用钩子。如果是钩子的话,子类可以选择实现这个钩子,但并不强制子类一定要这么做。

    三、OO 原则和好莱坞原则

    OO原则:
        封装变化;多用组合,少用继承;针对接口编程,不针对实现编程;为交互对象之间的松耦合设计而努力;类应该对扩展开放,对修改关闭;依赖抽象,不要依赖具体;只和朋友交谈;别找我,我会找你

    好莱坞原则:别调用我们,我们会调用你。

        好莱坞原则可以给我们一种防止“依赖腐败”的方法。当高层组件依赖底层组件,而底层组件又依赖高层组件时,而高层组件又依赖边侧组件,而边侧组件又依赖底层组件时,依赖腐败就产生了。在这样的情况下没有人可以轻易地搞清楚系统的设计原理。但是在好莱坞原则下,我们允许底层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些底层组件。简而意之,高层组件对底层组件的方式是“别调用我们,我们会调用你的”

    四、问题:
    (1)好莱坞原则和依赖倒置原则之间关系?
        依赖倒置原则是让我们尽量避免使用具体类,而多使用抽象。而好莱坞原则是用在创建框架或者组件上的一种技巧,好让底层组件能够被挂钩进行计算中,而且又不会让高层组件依赖底层组件。两者的目标都是在于解耦,但是依赖倒置原则更加注重如何在设计中避免依赖。好莱坞原则则是教会我们一个技巧,创建一个有弹性的设计,允许底层结构能够相互操作,而又防止其他类太过依赖它们。

    (2)底层组件不可以调用高层组件中方法吗?
        并非如此,事实上,底层组件在结束时,常常会调用从超类中继承来的方法。我们所要做的是,避免让高层和底层组件之间有明显的环状依赖。

    (3)在Java API中,有哪些使用了模板方法?
    java.io的InputStream类的read()方法,是由子类实现的,而这个方法又会被read(byte b[],int off,int len)模板方法使用。代码如下:

     /**
         * Reads the next byte of data from the input stream. The value byte is
         * returned as an <code>int</code> in the range <code>0</code> to
         * <code>255</code>. If no byte is available because the end of the stream
         * has been reached, the value <code>-1</code> is returned. This method
         * blocks until input data is available, the end of the stream is detected,
         * or an exception is thrown.
         *
         * <p> A subclass must provide an implementation of this method.
         *
         * @return     the next byte of data, or <code>-1</code> if the end of the
         *             stream is reached.
         * @exception  IOException  if an I/O error occurs.
         */
        public abstract int read() throws IOException;
    

      

    public int read(byte b[], int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException();
            } else if (off < 0 || len < 0 || len > b.length - off) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return 0;
            }
    
            int c = read();
            if (c == -1) {
                return -1;
            }
            b[off] = (byte)c;
    
            int i = 1;
            try {
                for (; i < len ; i++) {
                    c = read();
                    if (c == -1) {
                        break;
                    }
                    b[off + i] = (byte)c;
                }
            } catch (IOException ee) {
            }
            return i;
        }

    五、模板发放模式和策略模式对比
    (1)策略模式定义一个算法簇,并让这些算法可以互换。正因为每个算法都是被封装起来的,所以对外可以轻易的使用不同的算法。
    (2)模板方法模式定义一个算法的大纲,而由子类定义其中的具体实现,所以在算法中可以有不同的实现细节,但是整体的算法的结构依然维持不变。
    (3)策略模式采用的是组合的方式实现,而模板方法模式采用的是继承的方式实现
    (4)模板方法模式,除了极少的部分之外,它的算中每个部分都是相同的,会重复使用到的代码都被放进了超类中,让所有的子类共享。策略模式采用的是组合的方式,所以更加有弹性,可以在运行时改变他们的算法,而只需要改用不同的策略对象即可。
    (5)模板方法模式在超类中提供了一个基础的方法,达到代码复用,并允许子类指定行为,由此它的依赖程度会比策略模式高。

    六、总结
    1).模板方法定义了算法的步骤,把这些步骤的实现延迟到子类。
    2).模板方法模式为我们提供了一种代码复用的重要技巧。
    3).模板方法的抽象类可以定义具体方法,抽象方法和钩子。
    4).抽象方法由子类实现
    5).钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要去覆盖它。
    6).为了防止子类改变模板方法中的算法,可以将模板方法申明成final
    7).好莱坞原则告诉我们,将决策权放在高层模板中,以便决定如何以及何时调用底层模块
    8).你将在真实世界代码中看到模板方法模式的许多变体,不要期待它们全都是一眼就可以被你认出的。
    9).策略模式和模板方法模式都是封装算法,一个用组合一个是用继承
    10).工厂方法时模板方法的一种特殊版本

  • 相关阅读:
    android 上面的视频播放
    android 中的 xml 解析方法
    database is locked
    Ubuntu 下获取 debug.keystore 的MD5
    Ubuntu 真机 调试
    PreferenceActivity 的用法总结
    WebView 相关知识点
    android 知识点
    Thread 中的 中断
    Java 追加数据到文件
  • 原文地址:https://www.cnblogs.com/lovegrace/p/12218294.html
Copyright © 2011-2022 走看看