Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to completely kill the if else in the code

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article focuses on "how to completely kill the if else in the code", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Now let the editor take you to learn "how to completely kill the if else in the code"!

Disgusting if-else

Suppose we want to make a takeout platform, and there is a demand like this:

In order to promote sales, a store on the takeout platform has set up a variety of member discounts, including 20% discount for super members, 10% discount for ordinary members and no discount for ordinary users.

It is hoped that when the user pays, according to the user's membership level, we can know which discount strategy the user meets, and then give a discount and calculate the amount payable.

With the development of the business, the new demand requires exclusive members to enjoy the discount only when the order amount of the store is more than 30 yuan.

Then, there is another abnormal demand, if the user's super member has expired, and the expiration time is within a week, then the user's single order will be discounted according to the super member, and a strong reminder will be made at the cashier to guide the user to reopen a member, and the discount will be carried out only once.

So, we can see the following pseudo code:

Public BigDecimal calPrice (BigDecimal orderPrice, String buyerType) {if (the user is an exclusive member) {if (the order amount is greater than 30 yuan) {returen 30% discount price;}} if (user is a super member) {return 20% discount price } if (the user is an ordinary member) {if (this user's super member has just expired and has not yet used a temporary discount) {temporary discount usage update (); returen 20% discount price;} return 10% discount price;} return original price;}

The above is a part of the price calculation logic for this requirement, using pseudo-code is so complex, if it is really writing code, the complexity can be imagined.

In such code, there is a lot of if-else and a lot of nesting of if-else, both of which are very low in readability and maintainability. So how can it be improved?

Strategy mode

Next, we try to introduce policy patterns to improve the maintainability and readability of the code.

First, define an interface:

/ * * @ author mhcoding * / public interface UserPayService {/ * calculate the price payable * / public BigDecimal quote (BigDecimal orderPrice);}

Then define several policy classes:

/ * * @ author mhcoding * / public class ParticularlyVipPayService implements UserPayService {@ Override public BigDecimal quote (BigDecimal orderPrice) {if (consumption amount greater than 30 yuan) {return 30% discount price;} public class SuperVipPayService implements UserPayService {@ Override public BigDecimal quote (BigDecimal orderPrice) {return 20% discount price }} public class VipPayService implements UserPayService {@ Override public BigDecimal quote (BigDecimal orderPrice) {if (this user's super member has just expired and has not yet used a temporary discount) {temporary discount usage update (); returen 20% discount price;} return 10% discount price;}}

After introducing the strategy, we can calculate the price as follows:

/ * * @ author mhcoding * / public class Test {public static void main (String [] args) {UserPayService strategy = new VipPayService (); BigDecimal quote = strategy.quote (300); System.out.println ("the final price of ordinary member goods is:" + quote.doubleValue ()); strategy = new SuperVipPayService (); quote = strategy.quote (300) System.out.println ("final price of super member goods is:" + quote.doubleValue ());}}

The above is an example. You can New the policy classes of different members in the code, and then execute the corresponding method of calculating the price.

However, for real use in code, such as in a Web project, there is no way to use the above Demo directly.

First of all, in the Web project, the policy classes we created above are hosted by Spring, and we are not going to New an instance ourselves.

Secondly, in the Web project, if you really want to calculate the price, it is also necessary to know the user's membership level in advance, such as finding out the membership level from the database, and then get different policy classes according to the level to implement the price calculation method.

So, for the real price calculation in the Web project, the pseudo code should look like this:

/ * * @ author mhcoding * / public BigDecimal calPrice (BigDecimal orderPrice,User user) {String vipType = user.getVipType (); if (vipType = = exclusive member) {/ / pseudo code: UserPayService strategy = Spring.getBean (ParticularlyVipPayService.class); return strategy.quote (orderPrice) } if (vipType = = Super member) {UserPayService strategy = Spring.getBean (SuperVipPayService.class); return strategy.quote (orderPrice);} if (vipType = = ordinary member) {UserPayService strategy = Spring.getBean (VipPayService.class); return strategy.quote (orderPrice);} return original Price;}

From the above code, we found that the maintainability and readability of the code seems to be better, but it does not seem to reduce if-else.

However, there is still a big disadvantage in the use of the policy pattern: the client must know all the policy classes and decide which one to use. This means that the client must understand the differences between these algorithms in order to select the appropriate algorithm class at the right time.

In other words, although there is no if-else when calculating the price, it is inevitable to have some if-else when choosing a specific strategy.

In addition, in the pseudo-code above, we implement the policy object of getting members from Spring, so how on earth should the code get the corresponding Bean?

Next, let's look at how to solve these problems with the help of Spring and factory mode.

Factory model

To make it easier for us to get the various policy classes of UserPayService from Spring, we create a factory class:

/ * * @ author mhcoding * / public class UserPayServiceStrategyFactory {private static Map services = new ConcurrentHashMap (); public static UserPayService getByUserType (String type) {return services.get (type);} public static void register (String userType,UserPayService userPayService) {Assert.notNull (userType, "userType can't be null"); services.put (userType,userPayService);}}

This UserPayServiceStrategyFactory defines a Map that holds instances of all policy classes and provides a getByUserType method that can directly get instances of the corresponding class based on the type. There is also a Register method, which we will talk about later.

With this factory class, the code that calculates the price can be greatly optimized:

/ * * @ author mhcoding * / public BigDecimal calPrice (BigDecimal orderPrice,User user) {String vipType = user.getVipType (); UserPayService strategy = UserPayServiceStrategyFactory.getByUserType (vipType); return strategy.quote (orderPrice);}

In the above code, if-else is no longer needed. After you get the user's vip type, you can call it directly through the factory's getByUserType method.

Through strategy + factory, our code has been greatly optimized, greatly improving readability and maintainability.

However, the above leaves a question, that is, how is the Map used to hold all instances of policy classes in UserPayServiceStrategyFactory initialized? How are the instance objects of each policy stuffed in?

Registration of Spring Bean

Remember the Register method provided in the UserPayServiceStrategyFactory we defined earlier? He is used to register for policy services.

Next, we'll find a way to call the Register method and register the Bean created by Spring through IOC.

For this requirement, you can borrow the InitializingBean interface provided in Spring, which provides Bean with a method of handling properties after initialization.

It includes only the afterPropertiesSet method, which is executed after the properties of the Bean are initialized by any class that inherits the interface.

So, let's modify the previous policy classes a little bit:

/ * @ author mhcoding * / @ Service public class ParticularlyVipPayService implements UserPayService,InitializingBean {@ Override public BigDecimal quote (BigDecimal orderPrice) {if (consumption amount greater than 30 yuan) {return 30% discount price;} @ Override public void afterPropertiesSet () throws Exception {UserPayServiceStrategyFactory.register ("ParticularlyVip", this) } @ Service public class SuperVipPayService implements UserPayService, InitializingBean {@ Override public BigDecimal quote (BigDecimal orderPrice) {return 20% discount price;} @ Override public void afterPropertiesSet () throws Exception {UserPayServiceStrategyFactory.register ("SuperVip", this) } @ Service public class VipPayService implements UserPayService,InitializingBean {@ Override public BigDecimal quote (BigDecimal orderPrice) {if (this user's super member has just expired and has not yet used a temporary discount) {temporary discount usage update (); returen 20% discount price;} return 10% discount price @ Override public void afterPropertiesSet () throws Exception {UserPayServiceStrategyFactory.register ("Vip", this);}}

You only need each implementation class of the policy service to implement the InitializingBean interface and its afterPropertiesSet method, in which you can call UserPayServiceStrategyFactory.register.

In this way, when Spring is initialized, when VipPayService, SuperVipPayService, and ParticularlyVipPayService are created, the Bean is registered with UserPayServiceStrategyFactory after the properties of Bean are initialized.

The above code, in fact, there is still some repetitive code, which can also be introduced into the template method mode to further simplify, we will not expand here.

In addition, when UserPayServiceStrategyFactory.register is called, the first parameter needs to pass a string, which can also be optimized here.

For example, you can use enumerations, or customize a getUserType method in each policy class and implement it individually.

At this point, I believe you have a deeper understanding of "how to completely kill the if else in the code". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report