Open Closed Principle With Service Locator Pattern

Open Closed Principle With Service Locator Pattern

Open closed principle is the most simple one in the list of software design principles I understand. "Open for extension, close for modification" - the idea seems quite straightforward. Let's create an example about validation.

We have a service which provides the feature to send message to recipients. The message's type could be SMS, Email, and Telegram, etc. Here is the structure of these message types.

Obviously, each message type has its own validation logic. SMSMessage must have valid recipient's phone number, EmailMessage must have valid receipient's email address, for example. We need a class to handle the validation and it might look like this.

    @Autowired
    @Qualifier("Email")
    private MessageValidator emailValidator;

    @Autowired
    @Qualifier("SMS")
    private MessageValidator smsValidator;

    @Autowired
    @Qualifier("Telegram")
    private MessageValidator telegramValidator;

    @Override
    public void processMessage(Message msg) {
        boolean isValid = false;
        if (msg instanceof SMSMessage) {
            isValid = smsValidator.validate(msg);
        } else if (msg instanceof EmailMessage) {
            isValid = emailValidator.validate(msg);
        } else if (msg instanceof TelegramMessage) {
            isValid = telegramValidator.validate(msg);
        }

        //do other processing
    }

 

When a new message type comes in, you have to change this class again to support the new type. This approach violate the open closed principle.

To deal with this, we use the ServiceLocatorFactoryBean provided by Spring framework to support the new validation without changing the existing code, we only need to create more classes to handle the validation logic of the new message type.

As you can see the code fragment below has been incredibly shortened.

    @Autowired
    private MessageValidatorFactory msgValidatorFactory;

    @Override
    public void processMessage(Message msg) {
        boolean isValid = msgValidatorFactory.getMsgValidator(msg.getType()).validate(msg);

        //do other processing
    }

public interface MessageValidatorFactory {
    MessageValidator getMsgValidator(String msgType);
}
@Configuration
public class BeanConfigs {
    @Bean("validatorFactory")
    public FactoryBean serviceLocatorFactoryBean() {
        ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();
        factoryBean.setServiceLocatorInterface(MessageValidatorFactory.class);
        return factoryBean;
    }
}

The configuration merely help to lookup the bean by beanId such as Email, SMS, Telegram

@Component("Email")
public class EmailMessageValidator implements MessageValidator {
    @Override
    public boolean validate(Message m) {
        //logic for validation
        return false;
    }
}
@Component("SMS")
public class SMSMessageValidator implements MessageValidator {
    @Override
    public boolean validate(Message m) {
        //logic for validation
        return false;
    }
}

 

@Component("Telegram")
public class TelegramMessageValidator implements MessageValidator {
    @Override
    public boolean validate(Message m) {
        //logic for validation
        return false;
    }
}

By this approach, your code will look much cleaner and become easier to maintain, mitigate the impact to the old features when implementing new feature.


Cheers

原文地址:https://hackernoon.com/open-closed-principle-with-service-locator-pattern-bb3f3voc

 

 

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: Age of Ai 设计师: meimeiellie
应支付0元
点击重新获取
扫码支付

支付成功即可阅读