Template mode and Policy mode of Android Architecture

Source: Internet
Author: User
The template method mode is one of the most common patterns in the gof design mode. In many popular frameworks (such as spring and struts), we can see the wide application of the template method pattern. The template method pattern is mainly used in Framework Design and is often used in daily application design. However, when we use the template method to solve our needs and design it, we often ignore some very important details. Ensure that the architecture logic is properly executed without being damaged by the quilt class; how can we extend the template method of the subclass. 1. The intention of the template method design pattern is usually caused by the following problem: We know the key steps required by an algorithm and determine the execution sequence of these steps. However, the specific implementation of some clustering is unknown, or the implementation of some clustering is related to the specific environment. The template method mode encapsulates steps that we do not know the specific implementation into abstract methods and provides specific methods to call them in the correct order (these methods are collectively referred to as template methods ), this constitutes an abstract base class. Child classes inherit from this abstract base class to implement the abstract methods of each step aggregation, while the workflow is controlled by the parent class. Consider a simple order processing requirement: a customer can order multiple goods (also known as the order items) in a single order, and the sales price of the goods is calculated based on the import price of the goods. Some goods can be discounted, while others cannot. Each customer has a credit line, and the total price of each order cannot exceed the customer's credit line. Based on the above business, we can know the steps required to process an order: 1. traverse the list of order list items and accumulate the total prices of all goods (calculate the sales price according to the order list items) 2. obtain the credit line of the customer based on the customer number. 3. write the customer number, the total price of the order, and the list of order items to the database. However, we cannot determine how to calculate the sales price of the shipping items, how to obtain the customer's credit limit based on the customer's number and write the order information to the database. Therefore, the order processing logic is determined by using an abstract class abstractorder, which defines undefined methods as abstract methods and completes specific implementation by sub-classes. Java code public abstract class extends actorder {public order placeorder (INT customerid, list orderitemlist) {int Total = 0; For (INT I = 0; I <orderitemlist. size (); I ++) {orderitem = (orderitem) orderitemlist. get (I); Total + = getorderitemprice (orderitem) * orderitem. getquantity ();} If (total> getspendinglimit (customerid) {Throw new businessexception ("credit limit exceeded" + getspendinglimit (customerid )) ;} Int orderid = saveorder (customerid, total, orderitemlist); return New orderimpl (orderid, total);} public abstract int getorderitemprice (orderitem ); public abstract int getspendinglimit (INT customerid); public abstract int saveorder (INT customerid, int total, list orderitemlist);} public abstract class extends actorder {public order placeorder (INT customerid, list orderitemlist) {int t Otal = 0; For (INT I = 0; I <orderitemlist. size (); I ++) {orderitem = (orderitem) orderitemlist. get (I); Total + = getorderitemprice (orderitem) * orderitem. getquantity ();} If (total> getspendinglimit (customerid) {Throw new businessexception ("Beyond Credit Limit" + getspendinglimit (customerid);} int orderid = saveorder (customerid, total, orderitemlist); return New orderimpl (orderid, total);} public abstract Int getorderitemprice (orderitem); public abstract int getspendinglimit (INT customerid); public abstract int saveorder (INT customerid, int total, list orderitemlist );} abstractorder determines the order processing logic in the placeorder method. The placeorder method is also called the template method. Three abstract methods are called in placeorder. Sub-classes only need to implement three abstract methods, and do not need to care about the order processing logic. 2. template method mode definition and structure template method mode is a behavior mode (gof95 ). Prepare an abstract class, define the skeleton of an algorithm in an operation, and declare some steps as abstract methods to force the subclass to implement them. Different subclasses can implement these abstract methods in different ways. The static structure of the template method mode consists of two participants in the template method mode for collaboration. Abstract template class: defines one or more abstract operations, which are implemented by sub-classes. These operations are called basic operations. Define and implement a specific operation. This operation is used to determine the top-level logic by calling basic operations. This operation is called the template method. Specific Class: implements the abstract operations defined by the abstract template class. As shown in the above Order Processing: abstractorder is the abstract template class, And placeorder is the abstract template method. The getorderitemprice, getspendinglimit, and saveorder abstract methods are basic operations. The specific subclass can implement these three abstract methods as needed. Different subclasses may have different implementation methods. Java code public class concreteorder extends actorder {public int getorderitemprice (orderitem) {// calculate the price of the goods ......} Public int getspendinglimit (INT customerid) {// read the customer's credit limit .....} Public int saveorder (INT customerid, int total, list orderitemlist) {// write to the database ......} Public class concreteorder extends actorder {public int getorderitemprice (orderitem) {// calculate the price of the goods ......} Public int getspendinglimit (INT customerid) {// read the customer's credit limit .....} Public int saveorder (INT customerid, int total, list orderitemlist) {// write to the database ......}} Concreteorder is a subclass of aggregactorder. concreteorder needs to complete three basic operations. It also has the same processing logic as the parent class. Delay implementation to subclass implementation, which is the benefit of the template method mode. 3. template method mode and control reversal "Don't call us, we will call you" is a famous Hollywood principle. In Hollywood, after you submit your resume to the performing arts company, you have to go home and wait. The Performing Arts Company has full control over the entire entertainment project. actors can only passively accept the company's poor performance and complete their own performances as needed. The template method mode fully embodies the "Hollywood" principle. The parent class completely controls the sub-class logic, which is the control inversion. Sub-classes can implement the variable part of the parent class, but inherit the logic of the parent class, and cannot change the business logic. 4. What is the template method mode and the open/closed principle "? The open/closed principle means that a software entity should be open to extensions and closed to modifications. That is to say, the software entity must be extended without being modified. The intent of the template method mode is to control the top-level logic by the abstract parent class, and postpone the implementation of basic operations to sub-classes. This means to reuse objects by means of inheritance, it also complies with the principle of opening and closing. The parent class is implemented through the top-level logic by defining and providing a specific method, which is also called the template method. Generally, this template method is the most important method for external objects. In the preceding order processing example, the Public Order placeorder (INT customerid, list orderitemlist) method is the most important method for external objects. Therefore, it must be public to be called by external objects. The subclass must inherit the parent class to extend the basic methods of the parent class, but it can also override the methods of the parent class. If the subclass overrides the template method of the parent class, it changes the top-level logic of the parent class control. This violates the "open and closed principle ". When using the template method mode, we should always ensure that the subclass has the correct logic. Therefore, the template method should be defined as final. Therefore, the placeorder method of the terraactorder class should be defined as the final Java code public final order placeorder (INT customerid, list orderitemlist) Public final order placeorder (INT customerid, list orderitemlist) the subclass cannot override a method defined as final. This ensures that the sub-class logic is always controlled by the parent class. In the template method mode, the template method of the abstract class should be declared as final. 5. Three main features of the template method mode and object encapsulation object-oriented: inheritance, encapsulation, and multi-State objects have internal and external behaviors. Encapsulation is used to hide information and maintain the integrity of internal data of objects. So that external objects cannot directly access the internal state of an object, but they must be accessed through appropriate methods. In Java, a specified modifier (public, protected, private) is assigned to the object attributes and methods for encapsulation, so that data is not maliciously accessed by external objects and methods are not called incorrectly, thus damaging the object encapsulation. Reducing the access level of a method, that is, maximizing the visibility of the method is an important encapsulation method. In addition to information hiding, the maximum method visibility can effectively reduce the coupling between classes and the complexity of a class. It can also reduce the number of errors that developers encounter. A class should only expose externally called methods. All methods that serve the public method should be declared as protected or private. If a method is not a public method, it must be extended or called by the quilt class. Define it as protected. otherwise, it should be private. obviously, the basic operations declared as abstract in the template method mode need to be implemented by the subclass. They only serve the template method placeorder. They should not be made public by abstractorder, so they should be protected. java code: protected abstract int getorderitemprice (orderitem); protected abstract int getspendinglimit (INT customerid); protected abstract int saveorder (INT customerid, int total, list orderitemlist ); protected abstract int getorderitemprice (orderitem); protected abstract int getspendinglimit (INT customerid); protected abstract int saveorder (I NT customerid, int total, list orderitemlist); in the template method mode, the basic method should be declared as protcted abstract 6. the template method mode and Hook method discussed above apply the template method mode to a business object. In fact, frameworks frequently use the template method mode, allowing the framework to implement centralized control over key logic. Think about this requirement: we need to create a base class for the basic spring applications to perform unit tests on the class methods. We know that the spring application defines all the objects to be used in an external XML file, also known as context. We usually divide the context into multiple small files for ease of management. During the test, we need to read the context file, but not read all the files every time. It takes a lot of time to read these files. Therefore, we want to cache the files as long as they are read once. Therefore, we can complete a test base class by extending the testcase class of JUnit. We need to implement the cache logic. Other developers only need to read the configuration file. It does not need to worry about whether it has a cache. Java code public encryption actcachecontexttests extends testcase {Private Static map contextmap = new hashmap (); protected configurableapplicationcontext applicationcontext; protected Boolean hascachedcontext (Object contextkey) {return contextkeytocontextmap. containskey (contextkey);} protected configurableapplicationcontext getcontext (Object key) {string keystring = contextkeystring (key); configurablea Pplicationcontext CTX = (configurableapplicationcontext) contextkeytocontextmap. get (keystring); If (CTX = NULL) {If (Key instanceof string []) {CTX = loadcontextlocations (string []) Key);} contextkeytocontextmap. put (keystring, CTX);} return CTX;} protected string contextkeystring (Object contextkey) {If (contextkey instanceof string []) {return stringutils. arraytocommadelimitedstring (string []) Contextkey);} else {return contextkey. tostring () ;}} protected configurableapplicationcontext loadcontextlocations (string [] locations) {return New classpathxmlapplicationcontext (locations);} // override the setup method of testcase, read the context file from the cache before running the test method. If the file does not exist in the cache, initialize applicationcontext and put it in the cache. protected final void setup () throws exception {string [] contextfiles = getconfiglocations (); applicationcontext = Ge Tcontext (contextfiles);} // read the context file. The subclass implements protected abstract string [] getconfiglocations ();} public extends actcachecontexttests extends testcase {Private Static map contextmap = new hashmap (); protected configurableapplicationcontext applicationcontext; protected Boolean hascachedcontext (Object contextkey) {return contextkeytocontextmap. containskey (contextkey);} protected configurableapplication Context getcontext (Object key) {string keystring = contextkeystring (key); ableableapplicationcontext CTX = (configurableapplicationcontext) contextkeytocontextmap. get (keystring); If (CTX = NULL) {If (Key instanceof string []) {CTX = loadcontextlocations (string []) Key);} contextkeytocontextmap. put (keystring, CTX);} return CTX;} protected string contextkeystring (Object contextkey) {If (contextkey INS Tanceof string []) {return stringutils. arraytocommadelimitedstring (string []) contextkey);} else {return contextkey. tostring () ;}} protected configurableapplicationcontext loadcontextlocations (string [] locations) {return New classpathxmlapplicationcontext (locations);} // override the setup method of testcase, read the context file from the cache before running the test method. If the file does not exist in the cache, initialize applicationcontext and put it in the cache. protected final void setup () throws exception {strin G [] contextfiles = getconfiglocations (); applicationcontext = getcontext (contextfiles);} // read the context file. The subclass implements protected abstract string [] getconfiglocations ();} in this way, the subclass only needs to implement the getconfiglocations method and provide the configuration file character array to be read. You do not need to worry about how to read the content of the context file and implement caching. Javasactcachecontexttests ensures that the context file is read before all tests are run. Note that the setup method is declared as protected because the setup method is a method of the testcase class. Here, the setup method is defined as final, which ensures that the subclass cannot override this method, thus ensuring the logic of the parent class control. Here we will find a problem. If you have used JUnit, you will understand what went wrong. The setup method of testcase performs initialization before the test method of this test class is run. For example, create public objects that are required for all test methods. After the setup method is declared as final, the subclass can no longer expand it, and some additional initialization actions are required for the subclass. You may say, "just remove the final modifier of the setup method ". This is acceptable, but after the final modifier is removed, the subclass can override the setup method and execute some additional initialization. The terrible thing is that the parent class has lost the logic that must read the context file and cache the context content. To solve this problem, we implement an empty method onsetup. Call the onsetup method in the setup method. In this way, the subclass can perform additional initialization by overwriting the onsetup method. // Override the setup method of testcase and read the context file from the cache before running the test method. If the context file does not exist in the cache, initialize applicationcontext and put it in the cache. java code protected final void setup () throws exception {string [] contextfiles = getconfiglocations (); applicationcontext = getcontext (contextfiles); onsetup ();} protected void onsetup () {} // read the context file. The subclass implements protected abstract string [] getconfiglocations ();} protected final void setup () throws exception {string [] Contextfiles = getconfiglocations (); applicationcontext = getcontext (contextfiles); onsetup () ;}protected void onsetup () {}// read the context file, the subclass implements protected abstract string [] getconfiglocations ();} Why not declare onsetup as abstract? This is because the subclass does not always need to override the onsetup method. The onsetup method is used to expand the setup method. Empty methods such as onsetup are called hookmethod. 7. The template method mode and Policy mode template method mode have the same effect as the policy mode. Sometimes the policy mode can be used to replace the template method mode. The template method mode achieves code reuse through inheritance, and the policy mode uses delegation, which is more flexible than inheritance. Inheritance is often used incorrectly. The policy mode aggregates uncertain behaviors into an interface and delegates the interface to the main class. Think about the order processing example above and change it to the rule mode. 1. Extract uncertain behaviors into an interface. Java code: public interface orderhelper {public int getorderitemprice (orderitem); Public int getspendinglimit (INT customerid); Public int saveorder (INT customerid, int total, list orderitemlist );} public interface orderhelper {public int getorderitemprice (orderitem); Public int getspendinglimit (INT customerid); Public int saveorder (INT customerid, int total, list orderitemlist);} 2 And call the corresponding method of this interface to implement the specific logic. Java code public class order {private orderhelper orderhelpr; Public void setorderhelper (orderhelper) {This. orderhelper = orderhelper;} public order placeorder (INT customerid, list orderitemlist) {int Total = 0; For (INT I = 0; I <orderitemlist. size (); I ++) {orderitem = (orderitem) orderitemlist. get (I); Total + = orderhelpr. getorderitemprice (orderitem) * orderitem. getquantity () ;} If (total> orderhelpr. getspendinglimit (customerid) {Throw new businessexception ("Beyond Credit Limit" + orderhelpr. getspendinglimit (customerid);} int orderid = orderhelpr. saveorder (customerid, total, orderitemlist); return New orderimpl (orderid, total) ;}} public class order {private orderhelper orderhelpr; Public void setorderhelper (orderhelper) {This. orderhelper = orderhelper;} public Order placeorder (INT customerid, list orderitemlist) {int Total = 0; For (INT I = 0; I <orderitemlist. size (); I ++) {orderitem = (orderitem) orderitemlist. get (I); Total + = orderhelpr. getorderitemprice (orderitem) * orderitem. getquantity ();} If (total> orderhelpr. getspendinglimit (customerid) {Throw new businessexception ("Beyond Credit Limit" + orderhelpr. getspendinglimit (customerid);} int orderid = ORD Erhelpr. saveorder (customerid, total, orderitemlist); return New orderimpl (orderid, total) ;}} this order class is no longer an abstract class, but a specific class. The Order class delegates the orderhelpher interface to complete the basic operations required by the placeorder method. In this case, the use of the rule mode is more advantageous, And the rule mode does not need to be inherited. It is implemented through a delegate object. The orderhelper interface does not need to continue with any specified class. In contrast, policy-based implementation is more complex. It can be seen that the template method mode is mainly used in framework design to ensure the logical sequence of the base class control processing process (such as framework initialization ). As in the test base class above. The framework usually needs to be reversed. In the following situations, the policy mode is used first: when many operations need to be changed, the policy mode is used to extract these operations to an interface. When the implementation of basic operations needs to be related to other classes, the policy mode should be used. The behavior and implementation are completely separated through the delegate interface (such as data access ). For example, the saveorder Method for order processing is written to the database. Its implementation is related to the persistence mode you adopt. When the implementation of some basic operations may need to be changed at runtime, it can be implemented by changing the delegate object at runtime, but inheritance cannot. Therefore, the policy mode is used.
Related Article

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.