Home  >  Article  >  Java  >  Implementation of Strategy Pattern in Java Design Patterns

Implementation of Strategy Pattern in Java Design Patterns

王林
王林forward
2023-04-24 23:37:061851browse

1 Overview

In daily development, we often encounter a situation where there are many algorithms or strategies to implement a function. We can implement this function based on different algorithms or strategies. For example: If you want to calculate a logistics calculation method, all are billed. Different express delivery has different billing methods, such as JD Express, Best Express, and YTO Express. The way they calculate shipping costs is different. So how do we achieve it? The simple ones are if...else...or switch...case.... These two implementations are called hard coding. If there is a new billing method like Yunda Express, then we need to modify the source code of our algorithm. This will make the code bloated and difficult to maintain.

So, we need to implement a way that each has its own algorithm, and we only need to choose which method to call on the client.

2 Strategy pattern

2.1 Components

Environment class (Context): Configured with a ConcreteStrategy object. Maintain a reference to the Strategy object. You can define an interface to let Strategy access its data.

Abstract Strategy Class (Strategy): Defines the public interface of all supported algorithms. Context uses this interface to call an algorithm defined by a ConcreteStrategy.

Concrete Strategy Class (ConcreteStrategy): Implement specific algorithms with Strategy interface.

2.2 Code Example

Take the freight rates of different express companies as an example:

Step 1: Define an abstract strategy class (billing method)

public interface CommandStrategy {
    /**
     * 计费方式
     * @param message
     */
    void calMoney(String message);
}

Steps Two: Define a specific strategy class (different algorithm classes implement this interface)

public class BaiShiCommand implements CommandStrategy {
    /**
     * 百世快递计费方式
     * @param message
     */
    @Override
    public void calMoney(String message) {
        System.out.println("百世快递收费方式:"+"起步20,每公斤6元");
    }
}
public class JingDongCommand implements CommandStrategy {
    /**
     * 京东快递计费方式
     * @param message
     */
    @Override
    public void calMoney(String message) {
        System.out.println("京东快递收费方式:"+"起步30,每公斤5元");
    }
}
public class YuanTongCommand implements CommandStrategy {
    /**
     * 圆通快递计费方式
     * @param message
     */
    @Override
    public void calMoney(String message) {
        System.out.println("圆通快递收费方式:"+"起步10,每公斤8元");
    }
}

Step three: Define the environment class

public class CommandContext {
    public CommandStrategy getInstance(String commandType) {
        CommandStrategy commandStrategy = null;
        Map<String, String> allClazz = CommandEnum.getAllClazz();
        //拿到对应算法类对应的路径
        String clazz = allClazz.get(commandType.trim().toLowerCase());
        if (StringUtils.isNotEmpty(clazz)) {
            try {
                try {
                    //创建一个对象实例
                    commandStrategy = (CommandStrategy) Class.forName(clazz).newInstance();//调用无参构造器创建实例
                } catch (InstantiationException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        System.out.println("commandStrategy:"+commandStrategy);
        return commandStrategy;
    }
}

Define an enumeration class:

public enum CommandEnum {
    JingDong("京东", "com.liubujun.design.command.JingDongCommand"), BaiShi("百世", "com.liubujun.design.command.BaishiCommand"), YuanTong("圆通", "com.liubujun.design.command.YuanTongCommand");
    private String name;
    private String clazz;
    public static Map<String, String> getAllClazz() {
        Map<String, String> map = new HashMap<>(8);
        System.out.println("==================="+Arrays.toString(CommandEnum.values())+"================");
        for (CommandEnum commandEnum : CommandEnum.values()) {
            map.put(commandEnum.getCommand(), commandEnum.getClazz());
        }
        return map;
    }
    public String getCommand() {
        return name;
    }
    CommandEnum(String command, String clazz) {
        this.name = command;
        this.clazz = clazz;
    }
    public void setCommand(String command) {
        this.name = command;
    }
    public String getClazz() {
        return clazz;
    }
    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
}

Client :

public class MainStart {
    public static void main(String[] args) {
        String message = "京东";
        CommandContext commandContext = new CommandContext();
        //拿到message对应算法的对象实例
        CommandStrategy commandStrategy = commandContext.getInstance(message);
        commandStrategy.calMoney(message);
    }
}

In this way, the client can directly call which express billing method

Implementation of Strategy Pattern in Java Design Patterns

2.3 Advantages and Disadvantages

Advantages :

1) Related algorithm series The Strategy class hierarchy defines a series of reusable algorithms or behaviors for Context. Inheritance helps extract common functionality in these algorithms.

2) Provides a way to replace the inheritance relationship: Inheritance provides another way to support multiple algorithms or behaviors. You can directly subclass the Context class to give it different behavior. But this will hard code the behavior into the Context and mix the implementation of the algorithm with the implementation of the Context, making the Context difficult to understand, maintain and extend, and it cannot dynamically change the algorithm. You end up with a bunch of related classes, the only difference between them is the algorithm or behavior they use. Encapsulating the algorithm in an independent Strategy class allows you to change it independently of its Context, making it easy to switch, understand, and extend.

3) Eliminate some if else conditional statements: Strategy mode provides an alternative to using conditional statements to select the desired behavior. When different behaviors are stacked in a class, it is difficult to avoid using conditional statements to select the appropriate behavior. Encapsulating behavior in separate Strategy classes eliminates these conditional statements. Code with many conditional statements usually indicates the need to use Strategy mode.

4) Choice of implementation Strategy mode can provide different implementations of the same behavior. Customers can choose from different strategies based on different time/space trade-off requirements.

Disadvantages:

1) The client must know all the policy classes and decide which one to use: This model has a potential shortcoming, that is, a client must choose an appropriate one. Strategy must know the difference between these Strategies. At this point, specific implementation issues may have to be exposed to the customer. Therefore, Strategy mode is only needed when these different behavior variants are related to customer behavior.

2) Communication overhead between Strategy and Context: No matter whether the algorithm implemented by each ConcreteStrategy is simple or complex, they all share the interface defined by Strategy. Therefore it is possible that some ConcreteStrategy will not use all the information passed to them through this interface; a simple ConcreteStrategy may not use any of the information! This means that sometimes the Context will create and initialize parameters that will never be used. If such a problem exists, then tighter coupling between Strategy and Context will be needed.

3) The strategy pattern will result in the generation of many strategy classes: the number of objects can be reduced to a certain extent by using the flyweight pattern. Increased Number of Objects Strategy increases the number of objects in an application. Sometimes you can reduce this overhead by implementing the Strategy as a stateless object that can be shared by various Contexts. Any remaining state is maintained by the Context. Context passes this state on every request to the Strategy object. A shared Strategy should not maintain state between calls.

The above is the detailed content of Implementation of Strategy Pattern in Java Design Patterns. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete