[设计模式]策略模式

      策略模式感觉使用中还是很常见的,它属于行为型模式。具体的概念嘛什么的网上很多,而且网上都喜欢拿出行方式做例子,也不知道是不是出自同一篇文章。

      个人使用下来感觉策略模式用来处理if、else或者swich、case这样的代码最合适了。拿我在实际中的使用举例子:当前的程序需求是接收到某个地方传过来的HttpRequest,然后需要根据目前设备的状态来选择不同的方式来处理并组成HttpResponse,最后返回Response,另外,设备的状态由设备上报,云端不参与(这个地方后面讲状态模式与策略模式的区别的时候会用到)。废话不多说,直接撸代码上来:

    public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
        if (log.isDebugEnabled()) log.debug("PhoneCallHandler Handle phone call start = " + new Date());

        String userId = handlerInput.getRequestEnvelope().getContext().getSystem().getUser().getUserId();
        String deviceId = handlerInput.getRequestEnvelope().getContext().getSystem().getDevice().getDeviceId();
        if (log.isDebugEnabled()) log.debug("userId = " + userId + "deviceId = " + deviceId);
        String userPhoneNumber = PhoneControllerUtil.searchPhoneNumberByUserId(userId);

        //根据状态选择对应的策略
        String callId = "";
        PhoneStateEntity phoneStateEntity = PhoneControllerUtil.getPhoneState(userId, deviceId);
        if (phoneStateEntity == null) {
            stateStrategy = new IdleStateStrategy();
        } else {
            callId = phoneStateEntity.getCallId();
            switch (phoneStateEntity.getState()) {
                case "ACTIVE":
                    stateStrategy = new ActiveStateStrategy();
                    break;
                case "TRYING":
                    stateStrategy = new TryingStateStrategy();
                    break;
                case "OUTBOUND_RINGING":
                    stateStrategy = new OutboundRingingStateStrategy();
                    break;
                case "INBOUND_RINGING":
                    stateStrategy = new InboundRingingStateStrategy();
                    break;
                case "IDLE":
                    stateStrategy = new IdleStateStrategy();
                    break;
                case "INVITED":
                    stateStrategy = new InvitedStateStrategy();
                    break;

            }
        }
        //================End===================

        //解析云端来的事件数据并分发给不同的策略
        Slot slot = intentRequest.getIntent().getSlots().get("SlotName");
        String value = slot.getValue();

        if (log.isDebugEnabled()) log.debug("PhoneCallHandler value = " + value);

        try {
            JSONObject jsonObject = JSON.parseObject(value);

            String name = null;
            String namePinyin = null;
            String targetPhoneNumber = null;
            String operation = null;

            String answer = jsonObject.getString("answer");
            JSONObject parameterObject = jsonObject.getJSONObject("parameters");

            if (parameterObject.containsKey("operation")) {
                operation = parameterObject.getString("operation");
            }

            if (operation == null) operation = "PHONE_CALL";
            ResponseBuilder builder = handlerInput.getResponseBuilder();
            Optional<Response> optional = null;
            switch (operation) {
                case "PHONE_CALL":
                    PhoneCallParameter phoneCallParameter = new PhoneCallParameter();
                    phoneCallParameter.setAnswer(answer);
                    phoneCallParameter.setUserPhoneNumber(userPhoneNumber);
                    if (parameterObject.containsKey("name")) {
                        name = parameterObject.getString("name");
                        phoneCallParameter.setName(name);
                    }
                    if (parameterObject.containsKey("name_pinyin")) {
                        namePinyin = parameterObject.getString("name_pinyin");
                        phoneCallParameter.setNamePinYin(namePinyin);
                    }
                    if (parameterObject.containsKey("phone_number")) {
                        targetPhoneNumber = parameterObject.getString("phone_number");
                        phoneCallParameter.setTargetPhoneNumber(targetPhoneNumber);
                    }
                    optional = stateStrategy.handlePhoneCall(builder, phoneCallParameter);
                    break;
                case "ACCEPT":
                    AcceptParameter acceptParameter = new AcceptParameter();
                    acceptParameter.setAnswer(answer);
                    acceptParameter.setCallId(callId);
                    optional = stateStrategy.handleAccept(builder, acceptParameter);
                    break;
                case "REFUSE":
                    RefuseParameter refuseParameter = new RefuseParameter();
                    refuseParameter.setAnswer(answer);
                    refuseParameter.setCallId(callId);
                    optional = stateStrategy.handleRefuse(builder, refuseParameter);
                    break;
                case "CALLING":
                    CallingParameter callingParameter = new CallingParameter();
                    callingParameter.setAnswer(answer);
                    optional = stateStrategy.handleCalling(builder, callingParameter);
                    break;
                case "SET":
                    SetParameter setParameter = new SetParameter();
                    setParameter.setAnswer(answer);
                    optional = stateStrategy.handleSet(builder, setParameter);
                    break;
                case "CHANGE":
                    ChangeParameter changeParameter = new ChangeParameter();
                    changeParameter.setAnswer(answer);
                    optional = stateStrategy.handleChange(builder, changeParameter);
                    break;
                case "RECORD":
                    RecordParameter recordParameter = new RecordParameter();
                    recordParameter.setAnswer(answer);
                    optional = stateStrategy.handleRecord(builder, recordParameter);
                    break;
                default:
                    optional = stateStrategy.handleDefault(builder, value);
                    break;
            }
            //================End===================

            if (optional == null) {
                log.error("PhoneCallHandler optional is null");
                optional = builder.withShouldEndSession(true).build();
            }
            if (log.isDebugEnabled()) log.debug("PhoneCallHandler Handle phone call end = " + new Date());
            return optional;
        } catch (Exception e) {
            log.error("PhoneCallHandler Handle phone error = " + e.toString());
            e.printStackTrace();
            return handlerInput.getResponseBuilder()
                    .withShouldEndSession(true)
                    .build();
        }
    }

      从代码里看,整体结构分为两部分,第一部分是根据当前的状态选择对应的策略,第二部分是用策略去处理不同的事件。如果不用策略模式,那么代码的结构就会变为:在每一个事件里都需要判断用户的状态,然后做对应的处理,这样代码不仅臃肿,而且维护起来很困难。使用了策略模式之后,只需要把对应的数据传递给不同的策略,具体怎么处理完全由对应的策略决定,不需要自己再关心处理逻辑,降低了耦合;而且当需要扩展,例如扩展新的状态的时候,那么就只需要增加对应的策略即可,可扩展性提高。但是缺点也很明显:类变多,有多少个策略就需要有多少个类。

      另外,这里可能会有人感觉疑惑(我当时就纠结了很久),就是既然是根据不同的状态去处理不同的业务,为什么不使用状态模式??这个地方其实是我想了很久才想到的,就是状态模式和策略模式到底有什么区别,网上搜了很多讲解,从各种讲解里来看,最大的区别就是状态模式里处理事件包含着状态的变化,但是策略模式不包含。从例子的角度来讲:策略模式以出行方式为例子,用户需要到达目的地,采用不同的出行方式,结果是;状态模式以桶放水为例子,在有水和没水的状态下处理方式不同。乍看之下感觉两者没什么区别,但是状态模式下有一点很容易忽略:桶在放水的过程中水会减少,很可能会有有水状态变为没水,此时会有状态的变化!!这里就是两者最大的区别。

      回到代码本身,这里不用状态模式的原因也就很清楚了:本身是选择策略依托于当前的状态,程序状态的变化不是自身导致的(完全由客户端上报),所以采用了策略模式,而没有使用状态模式。

      当然啦,这个部分完全是个人理解,理解的不对的地方还请大家指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值