In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article is about how to apply design patterns to your code. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.
Why use design patterns
Because the requirements of our project are always changing, in order to cope with this change, our code can be easily decoupled and expanded. If you can guarantee that the code will not change after it is written at once, you can think about how to write it.
How to determine where design patterns are needed
In our implementation, there is some code that is basically unchanged after being written at once, or that does not need to be extended, such as some tool classes, etc. Part of it often changes, and most of the design patterns are applied to the part where the requirements change. Analyze how the code will change and choose the appropriate design pattern to optimize this part of the code.
Take the demand for promotional activities as an example
Demand
In order to promote the sales of goods, the major merchandise stations will withdraw from some promotional activities to stimulate users' consumption during weekdays or some festivals, and the types of activities may be different, as follows:
Full reduction, full 400 minus 20
Voucher, Maserati 5 yuan coupon
Discount, 10% discount, 20% discount
For every full reduction, 10 for each full 200
Wait
Some of them can be superimposed, and some can only be used alone.
Simple implementation
The above requirements seem relatively simple, but if we consider that it is impossible for us to define all the promotion types at once, we may add new types at any time to ensure that we can easily implement the function extension. that would be troublesome. Do you know the summary of 9 design patterns used in the Spring framework?
When you get the demand first, you don't have to think about it so much. rolling up your sleeves is an operation:
Public class OrderPromotion {public BigDecimal promotion (Order order, int [] promotions) {for (int promotion:promotions) {switch (promotion) {case 1: / / calculate the price break after this type of discount Case 2: / / calculate the price after this type of discount break; case 3: / / calculate the price after this type of discount break; / /. } return order.getResultPrice ();}}
In terms of functional implementation alone, the above code has completed the basic functions.
But the above code is also fatal, although it may seem simple, but that is only because most functions are replaced with comments, and a method can take thousands of lines in the actual code.
Especially when we need to add new promotions, we need to add new types to switch, which is a disaster for development, and it is also a hassle to maintain the code.
Optimization 1: the principle of single responsibility
In the above code, promotion (...) The method completes all the work directly, but in our actual implementation, it is best to let a method have a single responsibility and only complete a certain function, so here we separate the judgment of the discount type from the calculation of the price:
Public class OrderPromotion {public BigDecimal promotion (Order order, int [] promotions) {for (int promotion:promotions) {switch (promotion) {case 1: calculate1 (order); break; case 2: calculate2 (order); break Case 3: calculate3 (order); break; / / more promotion}} return order.getResultPrice () } public void calculate1 (Order order) {/ / calculate the price after using discount one} public void calculate2 (Order order) {/ / calculate the price after using discount two} public void calculate3 (Order order) {/ / calculate the price after using discount three} / / more calculate}
Here we separate the judgment of the discount type from the calculation of the price, so that promotion (…) The amount of code of the method is greatly reduced, which improves the readability of the code. One of the six principles of face object design: the principle of single responsibility, this article is also recommended.
Optimization 2: strategy model
The optimized code above improves the readability of the original code, but the problem of the big explosion of the original OrderPromotion class code has not been solved.
To solve this problem, we want to be able to separate the calculated code from the current code. the first thing we can think of is to define a class, and then copy the calculated code to the class and call it when needed. In this way, it is true that it is separated, but it is a temporary cure rather than a permanent cure. Both classes need to be changed before adding new promotions.
Therefore, we hope to be able to separate the implementation of different promotional activities, so that the implementation of each activity is separate, and the modification will not affect the others. based on this, we can choose the strategy mode to achieve.
Strategy mode
The idea of the policy pattern is to encapsulate each algorithm into a separate class with a common interface, so that they can replace each other. The most important feature of the policy mode is that the algorithm can be changed without affecting the client, thus changing different functions.
Public class OrderPromotion {public BigDecimal promotion (Order order, int [] promotions) {for (int promotion:promotions) {switch (promotion) {case 1: new PromotionType1Calculate (order); break; case 2: new PromotionType1Calculate (order); break Case 3: new PromotionType1Calculate (order); break; / / more promotion}} return order.getResultPrice ();}}
The above code is obviously much more streamlined, and now if you need to add a promotion, you just need to define a promotion class, implement the PromotionCalculation interface, and then add it to switch.
Optimization 3: factory model
Although the above code has separated the implementation of the promotion, OrderPromotion has been changing, and each time you add or go offline, you need to modify the class.
Now we want OrderPromotion to be the same, peeling off the instantiation of PromotionCalculation. The creation of the class is obviously using the factory design pattern.
OrderPromotion
Public class OrderPromotion {public BigDecimal promotion (Order order, int [] promotions) {for (int promotion:promotions) {PromotionFactory.getPromotionCalculate (promotion) .requests (order);} return order.getResultPrice ();}}
The creation of the class is left to the factory.
Public class PromotionFactory {public static PromotionCalculate getPromotionCalculate (int promotion) {switch (promotion) {case 1: return new PromotionType1Calculate (order); break; case 2: return new PromotionType1Calculate (order); break; case 3: return new PromotionType1Calculate (order) Break; / / more promotion} return null;}}
After using the factory mode, the OrderPromotion class does not need to be changed, each time you add a new promotion, you just need to add it to the factory class.
Optimization 4: configuration + reflection
The problem with the above code is that every time you need to add a new promotion, you still need to modify the code in the factory class, which we solve by adding reflection to the configuration file.
Define Mapping Profil
Mapping.properties
1=design.order.PromotionType1Calculate 2=design.order.PromotionType2Calculate 3=design.order.PromotionType3Calculate
PromotionFactory
Public class PromotionFactory {private static Map mapping = new HashMap (); static {try {Properties pps = new Properties (); pps.load (new FileInputStream ("Test.properties")); Iterator iterator = pps.stringPropertyNames (). Iterator (); while (iterator.hasNext ()) {String key=iterator.next () Mapping.put (Integer.valueOf (key), pps.getProperty (key));}} catch (IOException e) {e.printStackTrace ();}} public static PromotionCalculate getPromotionCalculate (int promotion) throws Exception {if (mapping.containsKey (promotion)) {String beanName = mapping.get (promotion) Return Class.forName (beanName) .newInstance ();} return null;}
Through the above code, we can realize the flexible expansion of the function without changing the existing code. Of course, the code here is only used as a demonstration, and there are actually a lot of areas that can be improved, such as the low reflection efficiency in the end, and it can also be achieved in other ways.
Thank you for reading! This is the end of the article on "how to apply design patterns in code". I hope the above content can be of some help to you, so that you can learn more knowledge. If you think the article is good, you can share it for more people to see!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.