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

A tutorial on how to use Policy pattern based on Spring (Boot)

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

Share

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

This article mainly explains the "tutorial on the use of strategy patterns based on Spring (Boot)". The content of the explanation in this article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn the tutorial on the use of strategy patterns based on Spring (Boot).

Processing when policy mode is not in use

Take the Internet of things as an example, you may not be familiar with it. Here is a payment scenario. For example, in the process of payment, we may choose WeChat Pay, Alipay or silver card payment. At the same time, bank cards are divided into different banks, which are unified as bank cards here.

The simplest and most straightforward code implementation is as follows:

Public void pay (String payType) {if ("alipay" .equals (payType)) {System.out.println ("Alipay");} else if ("wechatPay" .equals (payType)) {System.out.println ("WeChat Pay");} else if ("bank" .equals (payType)) {System.out.println ("bank card payment");}}

In this way, compared with the design pattern, it usually does not conform to two principles: the single responsibility principle and the opening and closing principle.

We will find that the current class (or method) does not handle the functions of multiple businesses, and once any one payment method is modified, it may affect other payment methods. At the same time, it is not possible to open to extensions and close to modifications. When adding other payment methods, you also need to modify the ifelse judgment, which affects other business logic.

The strategy pattern usually solves the problem that there is a lot of ifelse processing logic, thus improving the maintainability, extensibility and readability of the code.

Outline of the policy pattern

Before making changes to the above code, let's take a look at the basic components of the policy pattern.

Policy pattern (Strategy) defines a set of algorithms that encapsulate each algorithm and make them interchangeable.

A policy pattern usually consists of the following parts:

Strategy policy class, which defines all common interfaces that support algorithms

ConcreteStrategy specific policy class, which encapsulates specific algorithms or behaviors, inherits from Strategy.

The Context context, configured with a ConcreteStrategy, maintains a reference to the Strategy object

The StrategyFactory policy factory class, which is used to create a concrete implementation of the policy class; usually this section can be omitted, depending on the situation. For example, in the subsequent example, the policy class is instantiated through Spring's dependency injection mechanism.

Represented by a class diagram (omitting the policy factory class), as shown below:

Image

Implementation of Policy pattern based on Spring

At present, in practice, the strategy pattern is usually implemented based on the characteristics of Spring, which is explained here as an example.

Policy class definition

As mentioned above, the policy class is used to define the interface of the function, which can be named PaymentService or PaymentStrategy for payment scenarios.

Public interface PaymentService {/ * pay * / PayResult pay (Order order);}

At the same time, different implementation classes of the policy class are provided: AlipayService, WeChatPayService, BankPayService.

@ Service ("alipay") public class AlipayService implements PaymentService {@ Override public PayResult pay (Order order) {System.out.println ("Alipay"); return null;}} @ Service ("wechatPay") public class WeChatPayService implements PaymentService {@ Override public PayResult pay (Order order) {System.out.println ("WeChatPay"); return null } @ Service ("bank") public class BankPayService implements PaymentService {@ Override public PayResult pay (Order order) {System.out.println ("BankPay"); return null;}}

The specific implementation can be instantiated through a PaymentFactory to build storage, or can be directly injected into the List or Map of Context in the form of @ Autowired.

The implementation of PaymentFactory is as follows:

Public class PaymentFactory {private static final Map payStrategies = new HashMap (); static {payStrategies.put ("alipay", new AlipayService ()); payStrategies.put ("wechatPay", new WeChatPayService ()); payStrategies.put ("bank", new BankPayService ());} public static PaymentService getPayment (String payType) {if (payType = = null) {throw new IllegalArgumentException ("pay type is empty.") } if (! payStrategies.containsKey (payType)) {throw new IllegalArgumentException ("pay type not supported.");} return payStrategies.get (payType);}}

Initialize the corresponding policy implementation class through the static static code block, and then provide a getPayment method to obtain the corresponding service according to the payment type. Of course, the block of code initialized by static is singleton stateless, and if you need a stateful class, the getPayment method needs to new a new object each time.

Public static PaymentService getPayment1 (String payType) {if (payType = = null) {throw new IllegalArgumentException ("pay type is empty.");} if ("alipay" .equals (payType)) {return new AlipayService ();} else if ("wechatPay" .equals (payType)) {return new WeChatPayService ();} else if ("bank" .equals (payType)) {return new BankPayService () } throw new IllegalArgumentException ("pay type not supported.");}

Context context

The Context context role, also known as Context encapsulation role, acts as a connecting link between the preceding and the following, shielding high-level modules from direct access to policies and algorithms, and encapsulating possible changes.

The above creates the implementation class of the policy class in the form of a factory, but of course you can also inject it directly into the Context context through @ Autowired.

@ Component public class PaymentStrategy {@ Autowired private final Map payStrategies = new HashMap (); public PaymentService getPayment (String payType) {if (payType = = null) {throw new IllegalArgumentException ("pay type is empty.");} if (! payStrategies.containsKey (payType)) {throw new IllegalArgumentException ("pay type not supported.");} return payStrategies.get (payType);}}

With the @ Autowired annotation above, the PaymentService implementation class instantiated by @ Service is injected into map, where key is the name of the instantiated class and value is the concrete instantiated class.

The above getPayment code is the same as in PaymentFactory. Of course, you can also encapsulate a pay method in PaymentStrategy so that the client can directly inject the PaymentStrategy class to call the pay method.

Public PayResult pay (String payType,Order order) {PaymentService paymentService = this.getPayment (payType); return paymentService.pay (order);}

Improvement scheme

The policy pattern has basically been implemented through the above code. When a new payment channel is added, there is no need to modify the PaymentStrategy-related code, just a new class that implements the PaymentService interface.

However, there is room for optimization here in the interface definition. For example, the judgment here is based on the name of the Bean, but in some cases it may be complex or multiple Service may be executed at the same time. At this point, you can improve the PaymentService interface and add a new method to verify whether the function is supported.

Public interface PaymentService {boolean isSupport (Order order); / * pay * / PayResult pay (Order order);}

The isSupport method is implemented by the implementation class to determine which functions you support.

At the same time, context classes can further take advantage of the Steam feature provided by Java8:

@ Component public class PaymentStrategy {/ * here use @ Autowired to inject all instances as List. * / @ Autowired private List paymentServices; public void pay (Order order) {PaymentService paymentService = paymentServices.stream () .filter ((service)-> service.isSupport (order)) .findFirst () .orElse (null); if (paymentService! = null) {paymentService.pay (order) } else {throw new IllegalArgumentException ("pay type not supported.");}

Through further modification, the program has become more flexible.

Thank you for your reading, the above is the content of the tutorial on the use of strategy patterns based on Spring (Boot). After the study of this article, I believe you have a deeper understanding of the tutorial on the use of strategy patterns based on Spring (Boot), and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

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