• 设计模式-模版方法


    模版方法(template method)

    在模板模式中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

    意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

    关键代码:在抽象类实现,其他步骤在子类实现。

    使用场景: 通常情况下,模板方法模式用于定义构建某个对象的步骤与顺序,或者定义一个算法的骨架。

    注意事项:

    对于模板方法模式,父类提供的构建步骤和顺序或者算法骨架,通常是不希望甚至是不允许子类去覆盖的,所以在某些场景中,可以直接将父类中提供骨架的方法声明为final类型。

    典型应用:ClassLoader.findClass(String name)

    类图:

    public abstract class ClassLoader {
        //定义一个父加载器的引用
        private final ClassLoader parent;
    
        //父类算法的定义
        protected Class<?> loadClass(String name, boolean resolve)
                throws ClassNotFoundException {
            synchronized (getClassLoadingLock(name)) {
                // First, check if the class has already been loaded
                Class<?> c = findLoadedClass(name);//1.先从缓存中查找当前类是否已经加载,如果找到直接返回
                if (c == null) {
                    long t0 = System.nanoTime();
                    try {
                        if (parent != null) {
                            c = parent.loadClass(name, false);//2.递归查找父加载器中是否已经加载此类
                        } else {
                            c = findBootstrapClassOrNull(name);//3.顶级父加载器BootstrapClassLoader是否已经此类
                        }
                    } catch (ClassNotFoundException e) {
                        // ClassNotFoundException thrown if class not found
                        // from the non-null parent class loader
                    }
    
                    if (c == null) {
                        // If still not found, then invoke findClass in order
                        // to find the class.
                        //依然未找到,自己加载当前类
                        long t1 = System.nanoTime();
                        c = findClass(name);//典型模版方法
    
                        // this is the defining class loader; record the stats
                        sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                        sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                        sun.misc.PerfCounter.getFindClasses().increment();
                    }
                }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }
    
        //抽象父类中的findClass方法并没有实现,只抛出了一个异常,交给子类选择性重写
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            throw new ClassNotFoundException(name);
        }
    }
    

      

    类加载器为何要使用模板模式给我们定义好查找的算法,是为了保证我们加载的每一个类在虚拟机当中都有且仅有一个。

    既然如此,为何不把loadClass方法写成final类型的,这样不是更安全吗?

    这是因为有的时候我们希望JVM当中每一个类有且仅有一个,但有的时候我们希望有两个,甚至N个,就比如我们的tomcat,你可以想象下,你每一个项目假设都有com.xxx.xxxx.BaseDao等等,如果这些类都是一个的话,你的tomcat还能同时启动多个WEB服务吗?虽说tomcat也是遵循的双亲委派模型,但是从此也可以看出来,我们并不是在所有时候都希望同一个全限定名的类在整个JVM里面只有一个。

       参考资料:https://blog.csdn.net/zuoxiaolong8810/article/details/9108189

            https://blog.csdn.net/qq_32555377/article/details/106333657

  • 相关阅读:
    inux修改profile文件出错后所有命令不能用
    windows常用批处理脚本
    Namespace + functions versus static methods on a class 命名空间函数和类的静态方法对比
    vs2008(visual studio)使用cppcheck
    保存文件为UTF8格式(Writing UTF8 files in C++).
    C++ smtp发送邮件类(ssl/tls)转自codeproject。
    CString、TCHAR、WCHAR 字符串等转BSTR的几种方法。
    C/C++中全局变量的那些事儿
    [C++] 哪本书是对程序员最有影响、每个程序员都该阅读的书?读书排行。
    (转)修改VS2008(vc)中工程/解决方案/类的名字
  • 原文地址:https://www.cnblogs.com/fireinthehole/p/13859559.html
Copyright © 2020-2023  润新知