The design pattern interview strategy and factory pattern replace the complex ifelse in the business scenario

Posted by tinkertron on Wed, 19 Jan 2022 14:18:57 +0100

The design pattern interview strategy and factory pattern replace the complex ifelse in the business scenario

I'm fat brother, an unprofessional interviewer!

I am embarrassed, a young rookie actively looking for a job!

What Xiaobai fears most in the interview is that the knowledge asked by the interviewer is too general and he can't quickly locate the key points!!!

Main interview sites in this period

How to use design patterns to replace complex in business scenarios ifelse?

VIP type

import java.util.Objects;

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 *
 * Membership type
 */
public enum VIPEnums {

    GOLD(1, "Gold member"),
    STAR(2, "Star Diamond member"),
    SPORTS(3, "Sports member"),
    FUN_VIP(4, "FUN member");

    private final int code;
    private final String desc;

    VIPEnums(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public int getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }

    public static VIPEnums getByCode(Integer code) {
        for (VIPEnums s : VIPEnums.values()) {
            if (Objects.equals(s.getCode(), code)) {
                return s;
            }
        }
        return null;
    }
}

VIP entity

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmeifeishi@163.com
 *
 * vip
 */
public class VIP {

    private VIPEnums vipType;

    // TODO VIP other attributes id, name

    public VIP() {
    }

    public VIP(VIPEnums vipType) {
        this.vipType = vipType;
    }

    public VIPEnums getVipType() {
        return vipType;
    }

    public void setVipType(VIPEnums vipType) {
        this.vipType = vipType;
    }
}

If else mode

// If else mode
public class App {
    public static void main( String[] args ) {

        // Gold member
        VIP vip = new VIP(VIPEnums.GOLD);

        if (vip.getVipType().getCode() == VIPEnums.GOLD.getCode()) {
            // TODO gold membership interests
        } else if (vip.getVipType().getCode() == VIPEnums.STAR.getCode()) {
            // TODO Star Diamond membership interests
        } else if (vip.getVipType().getCode() == VIPEnums.SPORTS.getCode()) {
            // TODO sports membership rights
        } else if (vip.getVipType().getCode() == VIPEnums.FUN_VIP.getCode()) {
            // TODO FUN membership interests
        } else {
            // TODO other members
        }

    }
}

Strategy mode

VIP policy interface

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 * VIP Policy interface
 */
public interface VIPStrategy {

    // VIP's rights and interests
    void equity();
}

Policy interface implementation class - Gold Member

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 *
 * Policy interface implementation class - Gold Member
 */
public class GoldVIPStrategyImpl implements VIPStrategy {

    @Override
    public void equity() {
        // Specific rights and interests of TODO Gold members
    }
}

Specific implementation class of policy interface - Star Diamond member

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 *
 * Specific implementation class of policy interface - Star Diamond member
 */
public class StarVIPStrategyImpl implements VIPStrategy {

    @Override
    public void equity() {
        // Specific rights and interests of TODO Star Diamond members
    }
}

Specific implementation class of policy interface - Sports member

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 *
 * Specific implementation class of policy interface - Sports member
 */
public class SportsVIPStrategyImpl implements VIPStrategy {

    @Override
    public void equity() {
        // Specific rights and interests of TODO sports members
    }
}

Policy interface implementation class - FUN member

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 *
 * Policy interface implementation class - FUN member
 */
public class FunVIPStrategyImpl implements VIPStrategy {

    @Override
    public void equity() {
        // Specific rights and interests of TODO FUN members
    }
}

Policy context class

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 *
 * Policy context class (holder of vip policy interface)
 */
public class VIPStrategyContext {

    private VIPStrategy vipStrategy;

    // Set VIP policy
    public void setVipStrategy(VIPStrategy vipStrategy) {
        this.vipStrategy = vipStrategy;
    }

    // Execute VIP benefits
    public void handle() {
        if (vipStrategy != null) {
            vipStrategy.equity();
        }
    }
}

Strategic factory

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 *
 * VIP Strategic factory
 */
public class VIPStrategyFactory {

    private VIPStrategyFactory() {
    }

    public static VIPStrategy getVipStrategy(VIP vip) {
        VIPStrategy vipStrategy = null;
        
        if (vip.getVipType().getCode() == VIPEnums.GOLD.getCode()) {
            // Gold member policy implementation class
            vipStrategy = new GoldVIPStrategyImpl();
        } else if (vip.getVipType().getCode() == VIPEnums.STAR.getCode()) {
            // Star Diamond member policy implementation class
            vipStrategy = new StarVIPStrategyImpl();
        } else if (vip.getVipType().getCode() == VIPEnums.SPORTS.getCode()) {
            // Sports member strategy implementation class
            vipStrategy = new SportsVIPStrategyImpl();
        } else if (vip.getVipType().getCode() == VIPEnums.FUN_VIP.getCode()) {
            // FUN member policy implementation class
            vipStrategy = new FunVIPStrategyImpl();
        } else {
            // Other members
        }

        return vipStrategy;
    }
}

Simulate member login to obtain benefits

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 *
 * Simulate member login to obtain benefits
 */
public class TestStrategy {

    public static void main(String[] args) {

        // Gold member
        VIP vip = new VIP(VIPEnums.GOLD);

        // Policy context, performer
        VIPStrategyContext context = new VIPStrategyContext();

        // According to the member type, obtain the specific strategy of the member and obtain the golden member strategy
        VIPStrategy strategy = VIPStrategyFactory.getVipStrategy(vip);

        // Bind to performer
        context.setVipStrategy(strategy);

        // Implement the strategy of gold members and gold rights
        context.handle();
    }
}

We know that the policy pattern itself is designed to encapsulate a series of algorithms. These algorithms have commonalities and can be replaced with each other. The algorithm changes independently of the client using it. The client does not need to know the specific implementation of the algorithm, and the client only depends on the policy interface.

By using the combination of strategy mode and factory mode, does it feel tall? 😇

Of course, the most important thing is that it is more convenient for program expansion, which is more in line with the opening and closing principle. Open expansion and close modification. No matter how many new types of members are added, everyone only needs to inherit the policy interface to realize the rights and interests of new members.

Note that although it is conducive to extension, the disadvantages of the policy pattern are also obvious. When creating a specific policy implementation class, the policy factory still writes a large number of if else to judge, as shown in the figure

A small partner said that it seems similar to not using the strategy mode and factory mode???

Isn't it easier to pull out a method or encapsulate it into an object to call???

Next, let's talk about how to optimize the factory strategy.

First of all, our factory returns the corresponding policy implementation class after judging according to the member type of the current incoming user. Then we can use the collection to store the implementation class. The member type is used as the key to register all member policies in the map. It should be noted that the daily development is based on Spring for bean management. Of course, the policy classes that need to be created above all want to be dynamically managed by Spring, rather than new instances one by one.

The question is, how to implement managed registration of policy classes through spring?

The InitializingBean interface provided by Spring provides the bean with the processing method after property initialization. It only includes the afterpropertieset method. All classes that inherit this interface will execute this method after the property initialization of the bean. We use this method to register the bean created by Spring through IOC in the Map.

Transformation strategy factory

import org.example.model.VIP;
import org.example.strategy.VIPStrategy;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 * <p>
 * VIP Strategic factory
 */
public class VIPStrategyFactory {

    // Storage policy class instance
    public static Map<Integer, VIPStrategy> strategyMap = new ConcurrentHashMap<>();

    private VIPStrategyFactory() {
    }

    public static VIPStrategy getVipStrategy(VIP vip) {
        if (vip == null) {
            return null;
        }
        return strategyMap.get(vip.getVipType().getCode());
    }
}

Transform the policy class. After the bean attribute is initialized, register the instance object to the map in the factory class

Take gold members as an example:

import org.example.factory.VIPStrategyFactory;
import org.example.model.VIPEnums;
import org.example.strategy.VIPStrategy;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

/**
 * @author: Welcome to the feed letter boar: embarrassing fat
 * @date: 2021/12/16
 * @email: jiongmefeishi@163.com
 *
 * Policy interface implementation class - Gold Member
 */
@Service
public class GoldVIPStrategyImpl implements VIPStrategy, InitializingBean {

    @Override
    public void equity() {
        // Specific rights and interests of TODO Gold members
        System.out.println("Specific rights and interests of gold members");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        VIPStrategyFactory.strategyMap.put(VIPEnums.GOLD.getCode(), new GoldVIPStrategyImpl());
    }
}

Through the policy mode, factory mode and Spring's InitializingBean interface, a large number of if else have been solved, and the subsequent emergence of new VIP s is easier to expand. Of course, this is only a simple example of the idea of design mode. In practical application development, we should be flexible according to specific business scenarios. Small partners in need can also manually simulate some scenes, such as various new milk tea products in the milk tea shop. If you want to use the embarrassing example, you can reply 220110 on the boar and import the example to run.

Note: learn the principles of software design and never form obsessive-compulsive disorder. When you encounter complex business scenarios, you need to be flexible.

Learning design principles is the basis of learning design patterns. In the actual development process, it is not necessary to require all codes to follow the design principles, but to comprehensively consider manpower, time, cost and quality, do not deliberately pursue perfection, and follow the design principles in appropriate scenarios. This reflects a balanced trade-off, which can help us design a more elegant code structure.

Design pattern is also an art. Design patterns come from life. Don't use design patterns in order to apply design patterns.

Favorite friends, welcome to like collection and attention

Topics: Java Spring Design Pattern