Categories
Uncategorized

Work in common design patterns – Strategy Pattern

Foreword

Recent ready to learn before the next design patterns used in the project, where the code only shows the core business code, which go mostly unimportant omission.

Most of the code is working with small partners before coding out, and I’m here to do a study summary, I believe that to improve the technical capacity of all start with the beginning to imitate, learn other people’s code and design thinking is also a way to upgrade.

 

Follow-up will have observer mode, the chain of responsibility pattern blog outputs are working in the formal application to the scene output, see the article you want to be instructive and helpful.

I. Operational requirements

 
I did before demand online inquiry, the business complex, many nodes need to start pushing the message, such as doctors need to give the user a single push messaging and push, doctors need to give admissions users to send text messages, push, micro letters. Products said late there will be many different nodes trigger message sent.
 
Here began abstraction is, first sending a message, a lot of messages are the same strategy, but the assembled data is dynamic spliced, so abstract: Method buildSms (), buildPush (), buildWechat () like configuration message body, for splicing the same field are used the same strategy, included in the message a, B need physician id splicing message, the message C, D required by the user id splice message, then a, B can use the same strategy, C, D using another strategy.
 
Flowchart is as follows:
 
According to various business systems strategy to construct your own message body, and then send a underlying service by kafka, unified push a message.
 
 

Second, the strategy pattern

 
Strategy Mode (Strategy Pattern) refers to the object with a behavior, but in a different scenario, the act has a different algorithm. For example, a person’s tax rate related to his salary, the different wage levels corresponding to different tax rates.
Strategy mode is used object-oriented inheritance and polymorphism mechanisms to achieve the same behavior with different implementations in different scenarios.
Strategy Pattern nature: separation algorithm, choose to implement
 
Mainly addressed in a similar case of multiple algorithms, using the if … else or switch … and bloated complexity of the case brought by the.
 
 
Code Example:
 1 class Client {
 2     public static void main(String[] args) {
 3         ICalculator calculator = new Add();
 4         Context context = new Context(calculator);
 5         int result = context.calc(1,2);
 6         System.out.println(result);
 7     }
 8  
 9  
10     interface ICalculator {
11         int calc(int a, int b);
12     }
13  
14  
15     static class Add implements ICalculator {
16         @Override
17         public int calc(int a, int b) {
18             return a + b;
19         }
20     }
21  
22  
23     static class Sub implements ICalculator {
24         @Override
25         public int calc(int a, int b) {
26             return a - b;
27         }
28     }
29  
30  
31     static class Multi implements ICalculator {
32         @Override
33         public int calc(int a, int b) {
34             return a * b;
35         }
36     }
37  
38  
39     static class Divide implements ICalculator {
40         @Override
41         public int calc(int a, int b) {
42             return a / b;
43         }
44     }
45  
46  
47     static class Context {
48         private ICalculator mCalculator;
49  
50  
51         public Context(ICalculator calculator) {
52             this.mCalculator = calculator;
53         }
54  
55  
56         public int calc(int a, int b) {
57             return this.mCalculator.calc(a, b);
58         }
59     }}

 

Third, the actual code demonstrates

 
To code is simple and easy to understand, here are the core code fragment, the main way of looking and thinking strategies used to.
 

1, message enumeration class, where many messages as starting nodes, each node will correspond to an enumeration class contains the enumeration message, content push, micro-letters, private letters and the like.

 1 @Getter
 2 public enum MsgCollectEnum {
 3  
 4     /**
 5      * 枚举入口:用户首次提问 给医生 文案内容(医生id拼连接)
 6      */
 7     FIRST_QUESTION_CONTENT(2101, 1, MsgSmsEnum.SMS_FIRST_QUESTION_CONTENT, MsgPushEnum.PUSH_FIRST_QUESTION_CONTENT, MsgWechatEnum.WECHAT_FIRST_QUESTION_CONTENT);
 8  
 9  
10    /**
11      * 短信文案:用户首次提问 给医生 文案内容
12      */
13     SMS_FIRST_QUESTION_CONTENT(STTurnLinkEnum.DOCTOR_QUESTION_SETTING_PAGE.getStoapp(), "您好,有一位用户向您发起咨询,请确认接单,赶快进入APP查看吧!{0}");
14  
15  
16     /**
17      * Push文案:用户首次提问 给医生 文案内容
18      */
19     PUSH_FIRST_QUESTION_CONTENT(STTurnLinkEnum.DOCTOR_QUESTION_SETTING_PAGE.getStoapp(), STPushAudioEnum.PAY_SUCCESS.getType(), "您好, 有一位用户向您发起了咨询服务");
20  
21  
22     ......
23 }

 

 

2, the code message node triggers

Here it is to construct context MsgContext, logic main policy distribution in the last row, as the focus here will be to explain
 

1 MsgContext msgContext = new MsgContext();
2 msgContext.setDoctorId(questionDO.getDoctorId());
3 msgContext.setReceiveUid(questionDO.getDrUid());
4 msgContext.setMsgType(MsgCollectEnum.FIRST_QUESTION_CONTENT.getType());
5 this.stContextStrategyFactory.doStrategy(String.valueOf(msgContext.getMsgType()), QuestionMsgStrategy.class).handleSeniority(msgContext);

 

3, policy distribution

First, QuestionMsgStrategy.class find all beanMap correspondence, then find all the policy will be custom annotation class by finally find the specified implementation class msgType. Then we look at strategy implementation class
 
 1 @Slf4j
 2 public class STContextStrategyFactory {
 3     public extends STIContext, T extends STIContextStrategy> STIContextStrategy doStrategy(String type, Class clazz) {
 4         Map beanMap = STSpringBeanUtils.getBeanMap(clazz);
 5         if (MapUtils.isEmpty(beanMap)) {
 6             log.error("获取class:{} 为空", clazz.getName());
 7         }
 8         try {
 9             for (Map.Entry entry : beanMap.entrySet()) {
10                 Object real = STAopTargetUtils.getTarget(entry.getValue());
11                 STStrategyAnnotation annotation = real.getClass().getAnnotation(STStrategyAnnotation.class);
12                 List keySet = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(annotation.type());
13                 if (keySet.contains(type)) {
14                     return entry.getValue();
15                 }
16             }
17         } catch (Exception e) {
18             log.error("获取目标代理对象失败:{}", e);
19         }
20         log.error("strategy type = {} handle is null", type);
21         return null;
22     }
23 }

 
 

4, strategy implementation class

By custom annotations and then parse msgType find the specified value strategy class, sent by kafka msg different strategies class structure.
 
 1 @Component
 2 @STStrategyAnnotation(type = "2101-2104-2113-2016", description = "发给医生,无其他附属信息")
 3 public class QuestionMsgSimpleToDoctorStrategyImpl extends AbstractQuestionSendMsgStrategy {
 4  
 5  
 6     @Autowired
 7     private RemoteMsgService remoteMsgService;
 8     @Autowired
 9     private QuestionDetailService questionDetailService;
10  
11  
12     @Override
13     public StarSmsIn buildSmsIn(MsgContext context) {
14         // do something
15     }
16  
17  
18     @Override
19     public StarPushIn buildPushIn(MsgContext context) {
20         // do something
21     }
22  
23  
24     ......
25  
26  
27 }
28  
29  
30 @Slf4j
31 public abstract class AbstractQuestionSendMsgStrategy implements QuestionMsgStrategy {
32     /**
33      * 构建短信消息
34      *
35      * @param context
36      * @return
37      */
38     public abstract StarSmsIn buildSmsIn(MsgContext context);
39  
40  
41     /**
42      * 构建push消息
43      *
44      * @param context
45      * @return
46      */
47     public abstract StarPushIn buildPushIn(MsgContext context);
48  
49  
50     /**
51      * 构建微信公众号
52      *
53      * @param context
54      * @return
55      */
56     public abstract StarWeChatIn buildWeChatIn(MsgContext context);
57  
58  
59      @Override
60     public STResultInfo handleSeniority(MsgContext msgContext) {
61         // buildMsg and send kafka
62     }
63 }

 
 

Four, the disadvantages of the strategy model

Design of the entire messaging system was originally based on this policy pattern to achieve, but in the subsequent iterative development will find more and more bad maintenance, the main drawback as follows:
a, the access message push students need to understand the development of strategies for each class, for the same multiplexing strategy
b, more and more nodes, policy class more and more difficult to maintain the system
C, trigger node enumeration class scattered in various business systems, there is often the same of different nodes msgType
 
For the above disadvantages, and a reconstruction of the message system, the node configuration is completely scheme, providing a visual page configuration, the configuration of the message body to be written to the database through a configuration, the different code Alternatively dynamic placeholder data.
There is no longer shows the code of the new system, only needs access to the reconstructed structure msgContext can no longer need to manually write their own different kind of strategy.

Leave a Reply