[Summary of design patterns] Some Thoughts on common design patterns (To be continued ...), Design Pattern not complete to be continued

Source: Internet
Author: User

[Summary of design patterns] Some Thoughts on common design patterns (To be continued ...), Design Pattern not complete to be continued

Preface

In the [Java design patterns] series, LZ wrote more than a dozen articles on design patterns, roughly about the role, writing, advantages and disadvantages, and application scenarios of each design pattern.

With the growth of LZ, coupled with the reasons for engaging in certain architecture and underlying code design at work, in the past six months of practice, I have a new understanding of the design model, so I have this article to share my thoughts on the design model with my friends. LZ's own level is limited. I hope that my friends and friends can correct the mistakes and leave a message to discuss them.

 

Simple factory Mode

The first is the simple factory model.

The role of LZ in the simple factory model was described as follows:

The reason is simple: decoupling. To call object B of object A, the simplest way is to create A new object B. If class C and Class B implement the same interface/inherit from the same class, the system needs to change Class B to Class C, the program has to rewrite class A code. If there are 100 new B objects in the program, modify 100. This is the typical code that causes high coupling ". Therefore, there is A way to write A factory ifacloud, and A is coupled with ifacloud. Modify it so that all classes can implement the C interface and ifacloud can generate a c instance.

Thanks@I thought there was a problem with this passage. Now I think it's okay to look at it carefully. The simplest code example defines a factory class:

 1 public class ObjectFactory { 2  3     public static Object getObject(int i) { 4         if (i == 1) { 5             return new Random(); 6         } else if (i == 2) { 7             return Runtime.getRuntime(); 8         } 9         10         return null;11     }12     13 }

If the caller does not use the factory mode, I define a piece of code:

 1 public class UseObject { 2  3     public void funtionA() { 4         Object obj = new Random(); 5     } 6      7     public void funtionB() { 8         Object obj = new Random(); 9     }10     11     public void funtionC() {12         Object obj = new Random();13     }14     15 }

If I don't want to use the Random class now, I want to use the Runtime class. In this case, all three methods need to change "Object obj = new Random ()" to "Object obj = Runtime. getRuntime (); "if there are 100 and 1000 similar codes, you have to change them to 100 and 1000, which is very troublesome. The factory method is different, the caller can write like this:

1 public class UseObject {2 3 private static Properties properties; 4 5 static {6 // load configuration file 7} 8 9 public void funtionA () {10 Object obj = ObjectFactory. getObject (Integer. parseInt (properties. getProperty ("XXX"); 11} 12 13 public void funtionB () {14 Object obj = ObjectFactory. getObject (Integer. parseInt (properties. getProperty ("XXX"); 15} 16 17 public void funtionC () {18 Object obj = ObjectFactory. getObject (Integer. parseInt (properties. getProperty ("XXX"); 19} 20 21}

Create a configuration file. Each time the caller reads an enumerated value from the configuration file, the caller obtains an Object instance from ObjectFactory Based on the enumerated value. In this way, you can modify the configuration file once, regardless of 3, 100, or 1000, this is the benefit of using the factory model.

However, there is another small problem in the simple factory mode. if an object is added to the factory, the factory class must be added simultaneously if... else... branch, but this problem is not difficult to solve for the Java language, as long as the package path is defined, you can useReflectionYou do not need to modify the factory code.

After the above Lecture, LZ thinks that the main role of the simple factory model is as follows:

(1) hiding Object Construction Details

(2) separating the object user and the object constructor makes the code responsibility clearer and makes the overall code structure more elegant.

First, let's take a look at the first point. For example, JDK constructs different thread pools and finally obtains the ExecutorService interface implementation class:

1 @Test2 public void testExecutors() {3     ExecutorService es1 = Executors.newCachedThreadPool();4     ExecutorService es2 = Executors.newFixedThreadPool(10);5     ExecutorService es3 = Executors.newSingleThreadExecutor();6     System.out.println(es1);7     System.out.println(es2);8     System.out.println(es3);9 }

This method is relatively simple to construct a thread pool. For example, Spring constructs a Bean object:

1 @Test2 public void testSpring() {3     ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");4     Object obj = applicationContext.getBean(Object.class);5     System.out.println(obj);6         7     applicationContext.close();8     9 }

The intermediate process is very long (if you are interested, you can refer to several articles on Spring source code analysis I wrote ), the Bean construction details do not need to be exposed to Spring users (except for those who want to study the framework source code to better use the framework ), you only need to call a method of the factory class to obtain the desired object.

As for the second point mentioned above, we can use the single responsibility principle of the six principles of the design model to understand:

Single Responsibility Principle (SRP): 1. Definition of SRP (Single Responsibilities Principle): For a class, there should be only one reason for its change. In short, there is a single function. 2. If a class has too many responsibilities, it is equivalent to coupling these responsibilities together, A change in responsibility may weaken or restrain this class from fulfilling other responsibilities. This coupling will lead to a fragile design. When a change occurs, the design will suffer unexpected damages. 3. What software design really needs to do is to discover responsibilities and separate those responsibilities from each other.

My understanding of this passage is as follows:This method only focuses on usage. The construction object only focuses on the construction object and does not need to associate the two segments of logic to keep one class or method 100 ~ About 200 lines of code can clearly describe one thing to do..

 

Singleton Mode

The second point is the singleton mode.

Let's give an example of my favorite hunger Singleton mode:

 1 public class Object { 2  3     private static final Object instance = new Object(); 4      5     private Object() { 6          7     } 8      9     public static Object getInstance() {10         return instance;11     }12     13     public void functionA() {14         15     }16     17     public void functionB() {18         19     }20     21     public void functionC() {22         23     }24     25 }

Then, the following methods are used to call the functionA (), functionB (), and functionC () methods:

1 @Test2 public void testSingleton() {3     Object.getInstance().functionA();4     Object.getInstance().functionB();5     Object.getInstance().functionC();6 }

This is no problem. The Singleton mode ensures that the Object class is created only once in the Object pool (HEAP), saving the system overhead. But the problem is:Do you need to use the singleton mode? Why do you need to instantiate the Object?

Java contains the static keyword. if you add the static keyword to functionA (), functionB (), and functionC (), the caller can use the following method:

1 @Test2 public void testSingleton() {3     Object.functionA();4     Object.functionB();5     Object.functionC();6 }

Objects do not need to be instantiated. Isn't it more space-saving?

The difference between calling a method using the static keyword and calling a method using the singleton mode is summarized. What are the differences between the two methods? My personal opinion is:No difference. The so-called difference is, in the end, that is, the two types, which consume less memory and which call is more efficient, right? Let's take a look at them one by one:

  • In terms of memory consumption, there is no difference. static methods and instance methods all occupy a certain amount of memory, but these methods are loaded during class initialization, loaded and stored in the Method Area
  • There is no difference in call efficiency. methods are eventually translated as direct references in the parsing phase and stored in the method area, then call the method using this direct reference when calling the method. (If you have learned C and C ++, you may better understand this point. This is called a function pointer, this means that each method has an address in the memory. You can use this address to get the start position of the method and then start to call the method)

Therefore, no matter in terms of memory consumption or call efficiency, there is no big difference between calling methods in static mode and calling methods in singleton mode. Therefore, I think this Singleton method is used, it is also possible to directly write all methods as static. The Singleton mode is nothing more than a more object-oriented programming principle.

Writing code not only makes the code more elegant, concise, maintainable, and reusable, it is well known that it is not just a simple graph. How can it be written simply, in my personal opinion, which method is used to call the method is purely personal preferences. Let's talk about my personal principles:The entire class code is relatively small, with 100 or 200 or even fewer lines. The static method is used for direct calling without instantiating objects. The entire class code is relatively large, and the logic is complicated. The Singleton mode is used..

After all, this object still exists in a singleton and Singleton, which must be inherited. There are many class codes. One or more of them do not conform to my current business logic and cannot be inherited. If you use static methods to call them directly, you have to copy the entire class, it is relatively difficult to change several of the methods. If you use a Singleton, one or more of the methods do not conform to the current business logic. just inherit these methods. It doesn't matter if you copy and paste a few classes with less code.

 

Template Mode

The next step is the template mode. I have not written any articles on the template mode. Therefore, I found an article on the Internet that I think makes the template mode clear.

For an architect and CTO, the template mode is very important for programmers who write the underlying code. Template mode:The code designer defines the entire code processing process, abstracts the changes, and submits them to sub-classes for implementation.. Based on my own experience, the use of the template mode has two difficulties for code designers:

(1) The main process must be defined loose enough to ensure that the child classes have enough space to expand.

(2) The main process must be strictly defined to ensure that the extracted part is a key part.

These two points seem a little contradictory, but they are actually not contradictory. The first is from the scalability perspective, and the second is from the business perspective. Suppose there is such a piece of template code:

 1 public abstract class Template { 2  3     protected abstract void a(); 4     protected abstract void b(); 5     protected abstract void c(); 6      7     public void process(int i, int j) { 8         if (i == 1 || i == 2 || i == 3) { 9             a();10         } else if (i == 4 || i == 4 || i == 5) {11             if (j > 1) {12                 b();13             } else {14                 a();15             }16         } else if (i == 6) {17             if (j < 10) {18                 c();19             } else {20                 b();21             }22         } else {23             c();24         }25     }26     27 }

I don't know if this code example is appropriate, but I want to say what I want to say: this template code is well-defined, but lacks scalability. Because I thinkAdding too many business logic before and after the abstract method, such as too many conditions and too many loops makes it easy to put some logics that need to be abstracted so that the sub-classes can implement themselves into the public logic.This will cause two problems:

(1) The subdivision of the abstract part is too powerful, resulting in lower scalability. The subclass can only be written according to the defined logic. For example, some values in the () method must be in the c () the method can only be implemented through ThreadLocal or some public classes, but it increases the difficulty of the Code.

(2) The subclass finds that the abstract part is put in the public logic and cannot fulfill the Code requirements.

Finally, I think the template mode is very useful for organizing code ideas. Because the core of the template mode isAbstractionTherefore, when encountering complicated business processes, it is a good idea to use the template mode to abstract the core part to sort out the logic, at least I used this method to write a complex version of code.

 

Rule Mode

The policy mode is a design mode that can be considered as slightly different from the template mode. The difference between the policy mode and the template mode will be further discussed later.

The rule mode is actually relatively simple, but I have a little new understanding in use. For example:

1 public void functionA () {2 // a logical segment, 100 rows 3 4 System. out. println (); 5 System. out. println (); 6 System. out. println (); 7 System. out. println (); 8 System. out. println (); 9 System. out. println (); 10}

A normal method, funtionA (), contains a long segment (assuming it is the 100 lines of code here). When I change the code later, I find that these 100 lines of code are somewhat problematic, there are two ways to do this:

(1) Delete these 100 lines of code directly. But if you delete it directly, it is possible that the person who writes the code later wants to view the previously written code. What should I do? Some people have suggested using version management tools SVN and Git. Can't they view the code history? However, it is troublesome to view the code history every time. What if the network at that time was not good enough to view the code history?

(2) directly comment out the 100 lines of code and write the new logic below. In this way, you can view the previous code, but there are several hundred lines of comments that affect the readability of the Code and are not recommended.

At this time, we recommend that you use the policy mode. The logic of these 100 rows can be completely abstracted as a policy. The implementation of all policies is placed under a package, so that the original code is retained, you can conveniently view the package and change the policy as needed.

At the request of a netizen friend, add the Code. In this way, functionA () can be changed. First, define an abstract policy:

1 package org.xrq.test.design.strategy;2 3 public interface Strategy {4 5     public void opt();6     7 }

Then define A policy:

 1 package org.xrq.test.design.strategy.impl; 2  3 import org.xrq.test.design.strategy.Strategy; 4  5 public class StrategyA implements Strategy { 6  7     @Override 8     public void opt() { 9         10     }11     12 }

This is used in the following scenarios:

 1 public class UseStrategy { 2  3     private Strategy strategy; 4      5     public UseStrategy(Strategy strategy) { 6         this.strategy= strategy;  7     } 8      9     public void function() {10         strategy.opt();11         12         System.out.println();13         System.out.println();14         System.out.println();15         System.out.println();16         System.out.println();17         System.out.println();18     }19     20 }

When using the UseStrategy class, you only need to input new StrategyA () in the constructor. In this case, if you want to change the policy, you can define a policy B under the same package:

 1 package org.xrq.test.design.strategy.impl; 2  3 import org.xrq.test.design.strategy.Strategy; 4  5 public class StrategyB implements Strategy { 6  7     @Override 8     public void opt() { 9         10     }11     12 }

When UseStrategy class is used, you need to change the policy. You can input new StrategyB () in the constructor (). This method achieves my goal:

1. Code implementation is more elegant. The caller only needs to pass in the implementation of different Strategy interfaces.

2. The original code is retained because all the policies are placed in the same package, so you can easily view how the original code is written.

 

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.