(ix) Template method mode

Source: Internet
Author: User

Reprint: http://www.cnblogs.com/zuoxiaolong/p/pattern10.html

Template method mode, which is a lot of excellent open source projects in the LZ see the most of a design pattern, is also the LZ feel the most excellent design mode, so this chapter LZ will do its best to try to explain this design pattern clearly.

The template method pattern is generally used to unify the sub-class algorithm implementation steps, the use of a means or way. It defines the steps of a series of algorithms in the parent class, and defers the concrete implementation to the subclass.

The most typical form is an interface, an abstract parent class, a series of abstract methods in the parent class, and one by one implementations of these methods in subclasses.

Below the LZ to give an example, for example, we have an interface, inside a method, is used to create an HTML page, as follows.

Public interface Pagebuilder {    String bulidhtml ();    }

This interface is very simple, is to directly create an HTML page content, assuming that we do not use template method mode, directly let each subclass to directly implement this interface, then certainly the way of implementation is strange, and the steps are messy, this is really not conducive to maintenance and expansion. So we can use the template method pattern, the process to make a good, and then fill the specific content to the subclass, so that these subclasses generated HTML pages will be very consistent.

For this purpose, we define the following abstract classes to implement this interface, and we define the steps.

 public abstract class Abstractpagebuilder implements pagebuilder{private        StringBuffer StringBuffer = new StringBuffer (); Public String bulidhtml () {//First joins DOCTYPE because all are HTML pages, so our parent class does not need to defer to the subclass implementation, directly in the parent class implementation Stringbuffer.append ("<! DOCTYPE HTML public \ "-//W3C//DTD XHTML 1.0 transitional//en\" \ "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd\"        > "); Below the page is a pair of HTML tags, we also join in the parent class, do not need to implement stringbuffer.append for subclasses (" 

The above LZ has added a comment, this next we want to make an HTML page, directly inherit our abstract parent class, and our subclass only need to implement two template methods, we can successfully complete the creation of HTML page, the following LZ gives a subclass, we randomly create an HTML page.

public class Mypagebuilder extends abstractpagebuilder{    @Override    protected void Appendhead (StringBuffer StringBuffer) {        stringbuffer.append ("

Simply by adding a head and body tag, and then creating a test class to run, we'll see that we've generated an HTML page based on the standard template given by the parent class.

The advantage of doing this is that the parent class can standardize the creation of subclasses, which is easier for us to maintain, and the subclasses are more hassle--as DOCTYPE including HTML tags are the same, so subclasses no longer need to care about these. Of course, the above LZ write a bit rough, in fact, we can define a bit more carefully, such as the head tag, the first is the title, then the meta and so on. But as an example, we still follow the simple principle, mainly want to give you to convey the idea of template method mode.

The template method pattern is the most non-intrusive pattern in all design patterns, because its benefits are too obvious. The template method pattern does not force the implementation class of the interface to inherit, so it does not have any effect on the subclass, and if the implementation of the subclasses can match the template class template, then you can enjoy the benefits of the template method pattern.

Typically, a template method pattern is used to define the steps and order in which an object is built, or to define the skeleton of an algorithm.

The example we just made is obviously the process of building a string object, and here we declare that for the template method pattern, the parent class provides the build steps and the order or the algorithm skeleton, usually does not want to even allow subclasses to overwrite, so in some scenarios, you can The method that provides the skeleton in the parent class is declared as the final type directly.

The template method pattern also has a way of using, in order to give the subclass enough freedom, you can provide some methods for subclasses to cover, to implement some of the skeleton is not necessary but can have a custom implementation of the steps.

For example above, we should all know that there are some tags in the HTML page that are optional. such as meta tags, link tags, script tags, and so on. Then we can refine the example just to see what it says about how to cover the subclass. We have just refined the abstract parent class into the following form.

Public abstract class Abstractpagebuilder implements pagebuilder{private static final String Default_doctype = "<!d Octype HTML public \ "-//W3C//DTD XHTML 1.0 transitional//en\" \ "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd\"        > ";        private static final String Default_xmlns = "http://www.w3.org/1999/xhtml";        Private StringBuffer StringBuffer = new StringBuffer ();        Public String bulidhtml () {stringbuffer.append (default_doctype);        Stringbuffer.append ("

As you can see, we've refined the head tag generation process into four methods, Title,meta,link and script. But these four inside appendtitle are template methods, subclasses must be implemented, while the other three are normal empty methods.

Then the above three methods, is left to subclass coverage, of course, subclasses can choose not to overwrite, then the generated HTML will not meta,link and script these three kinds of tags, if you want to have, you can overwrite any of them, such as the following.

 public class Mypagebuilder extends abstractpagebuilder{protected void Appendmet A (StringBuffer stringbuffer) {stringbuffer.append ("<meta http-equiv=\" content-type\ "content=\" text/html; chars    Et=utf-8\ "/>");    } protected void Appendtitle (StringBuffer stringbuffer) {stringbuffer.append ("<title> Hello </title>"); } protected void Appendbody (StringBuffer stringbuffer) {stringbuffer.append ("<body> Hello, world!    </body> ");        } public static void Main (string[] args) {Pagebuilder pagebuilder = new Mypagebuilder ();    System.out.println (pagebuilder.bulidhtml ()); }    }

We covered the Appendmeta method, so we could generate a meta tag in the head tag. If you have seen the previous chapter of the adapter mode, in fact, this is similar to the default adaptation, the purpose is the same, because if the Appendmeta is also written as an abstract method, then the subclass must be implemented, but the META tag is not necessary, so the subclass is likely to put Appendmeta, The Appendlink,appendscript method is all empty.

so in order not to force subclasses to implement unnecessary abstract methods, but without depriving the subclass of the right to choose freely, we provide a default NULL implementation in the parent class to let subclasses choose whether or not to overwrite these methods.

When it comes to template method patterns, we have a class in the JDK and it has a story that has to be said, that is, the ClassLoader.

The JDK ClassLoader can be broadly divided into three categories: the Boot class loader, the extension classloader, and the application loader.

The paths for the three load classes are as follows:

start the ClassLoader : The Java_home/lib directory, and the path set by the-xbootcalsspath parameter, but the classes loaded by the bootloader are limited, and if the JVM does not know it, it is useless to put them in these directories.

extension ClassLoader : The Java_home/lib/ext directory, and the path specified by the Java.ext.dirs system variable.

application ClassLoader : The user's own classpath (CLASSPATH), which is the System class loader we use frequently, and the default parent ClassLoader for the abstract class ClassLoader in the JDK.

                 Here is why the class loader and template method patterns are related, because the ClassLoader class uses template mode to ensure uniqueness during class loading. LZ first show you the application of template pattern in this class.

 public abstract class ClassLoader {//This is an overloaded method public class<?> LoadClass (St    Ring name) throws ClassNotFoundException {return LoadClass (name, false); }//This is the definition of the parent class algorithm protected synchronized class<?> loadclass (String name, Boolean resolve) throws Classnot    foundexception {Class c = findloadedclass (name);        if (c = = null) {try {if (parent! = null) {c = Parent.loadclass (name, false);        } else {c = findBootstrapClass0 (name);        }} catch (ClassNotFoundException e) {c = findclass (name);    }} if (resolve) {resolveclass (c);    } return C; }//A method is left here to selectively overwrite the subclass protected class<?> Findclass (String name) throws ClassNotFoundException {throw new Cl    Assnotfoundexception (name); }}

The LZ intercepts the main part, in order to highlight these three methods. In the above LZ added a simple note, I believe that after the introduction, you should be able to see that this is a template method pattern, but it does not define an abstract method, because Findclass this method is not necessary to implement, so the JDK choice for the programmer to choose whether to overwrite.

From the code we can see that the order of the algorithms defined in ClassLoader is.

1, first of all to see if there are already loaded classes.

2, if the parent class loader is not empty, it is first loaded from the parent class ClassLoader.

3, if the parent class loader is empty, try to load from the boot loader.

4, if both fail, try to load from the Findclass method.

This is the parental delegation model of the JDK ClassLoader, which is loaded from the parent ClassLoader until the top of the inheritance system, otherwise it will be loaded with the current class loader. The purpose of doing this has just been said to be for class consistency in the JVM.

If the reader first contact with this knowledge, estimated will be more confused, the following LZ gives an example. Guess what the results of the following program will be?

Package Com.classloader;public class Classloadertest {public    static void Main (string[] args) throws Exception {        Class<?> clazz = Classloader.getsystemclassloader (). LoadClass ("Com.classloader.ClassLoaderTest");        Object entity = clazz.newinstance ();        SYSTEM.OUT.PRINTLN (Entity instanceof classloadertest);}    }

I'm sure you can guess with no doubt that the result should be true, because entity is an instance of the Classloadertest class, and the instanceof keyword is used to determine whether an instance belongs to a particular type, so the result is true.

Well, then, guess what the result of this code will be?

Package Com.classloader;import Java.io.ioexception;import Java.io.inputstream;class Myclassloader extends classloader{Public class<?> loadclass (string name) throws ClassNotFoundException {string fileName = Name.substring (Name.lastindexof (".")        +1) + ". Class";        InputStream is = GetClass (). getResourceAsStream (FileName);        if (is = = null) {return super.loadclass (name);            } try {byte[] b = new byte[is.available ()];            Is.read (b);        Return DefineClass (name, b, 0, b.length);        } catch (IOException e) {throw new ClassNotFoundException (); }}}public class Classloadertest {public static void main (string[] args) throws instantiationexception, illegal        Accessexception, classnotfoundexception {ClassLoader ClassLoader = new Myclassloader ();        Class<?> clazz = Classloader.loadclass ("Com.classloader.ClassLoaderTest");      Object entity = clazz.newinstance ();  SYSTEM.OUT.PRINTLN (Entity instanceof Classloadertest); }    }

Readers who are familiar with the ClassLoader may find the result to be unexpected, but perhaps some people will be more surprised, why is the result false?

This is because if the class is not loaded according to the skeleton algorithm provided in ClassLoader, it may cause two identical class information in the JVM, they are from a class file, but are not loaded by a loader, so these two classes are not equal.

This is also why the ClassLoader uses template mode to define the algorithm that we are looking for, to ensure that every class we load has and only one in the virtual machine.

But you might think, in that case, why not write the LoadClass method to the final type, which is not safer?

This is because sometimes we want every class in the JVM to have and only one, but sometimes we want two or even n, like our tomcat, you can imagine, Each of your project assumptions have Com.xxx.xxxx.BaseDao and so on, and if these classes are all one, can your Tomcat start multiple Web services at the same time? Although Tomcat also follows the parental delegation model, it can be seen from now on that we do not always want the same fully qualified class to have only one inside the entire JVM.

This refers to the class loader, is to give the template method an existing example of reality, so that some see more of their own manufacturing examples of readers can change the taste, if there is a chance, LZ will be in this series after the end of a dedicated series to share with you to learn the process of virtual machine insights, This time no more about the content of the ClassLoader.

In addition, if you know more about the class loader knowledge, or the usual work and study has a great help, you can also secretly search for the relevant information.

Well, the template method mode is introduced here, I hope you all have their own harvest.

Thank you for watching.

(ix) Template method mode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.