設計模式-職責鏈模式

littleni發表於2021-06-28

一、定義

職責鏈模式:使多個物件都有機會處理請求,從而避免請求的傳送者和接受者之間的耦合關係。將這個物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它為止。

二、程式碼實現

UML圖

定義一個抽象類AbstractHandler,提供一個對外方法handleRequest(),處理外部請求。抽象類分別有三個具體實現類,GuestHandler、CustomerHandler、MerchantHandler對應三種條件下的處理邏輯,如果不採用職責鏈設計模式,那麼通常就是通過if…else…實現,if customer … else if merchant … else if guest … else …

職責鏈設計模式,當提交一個請求時,由第一個AbstractHandler實現類處理,如果滿足條件則處理返回,否則移交給下一個AbstractHandler實現類處理,直至沒有下一個。這樣設計的好處符合開閉原則,每當新增一種條件,只需要增加一個AbstractHandler實現類,而不需要改動已有類,對擴充開放對修改封閉。

public abstract class AbstractHandler {

    private static final Logger log = LoggerFactory.getLogger(AbstractHandler.class);

    private AbstractHandler next;

    public AbstractHandler getNext() {
        return next;
    }

    public void setNext(AbstractHandler next) {
        this.next = next;
    }

    public void handleRequest(HandlerRequest request) {
        if (isHit(request)) {
            this.handle(request);
            return;
        }
        if (this.next != null) {
            this.next.handleRequest(request);
        } else {
            log.warn("no handler execute, request: {}", request);
        }
    }

    protected abstract boolean isHit(HandlerRequest request);

    protected abstract void handle(HandlerRequest request);

}
@Primary
@Order(1)
@Component
public class CustomerHandler extends AbstractHandler {

    private static final Logger log = LoggerFactory.getLogger(CustomerHandler.class);

    @Override
    protected boolean isHit(HandlerRequest request) {
        return request.getUserRole() == UserRole.CUSTOMER;
    }

    @Override
    protected void handle(HandlerRequest request) {
        log.info("handle customer execute, request: {}", request);
    }
}
@Order(2)
@Component
public class MerchantHandler extends AbstractHandler {

    private static final Logger log = LoggerFactory.getLogger(MerchantHandler.class);

    @Override
    protected boolean isHit(HandlerRequest request) {
        return request.getUserRole() == UserRole.MERCHANT;
    }

    @Override
    protected void handle(HandlerRequest request) {
        log.info("handle merchant execute, request: {}", request);
    }
}
@Order(3)
@Component
public class GuestHandler extends AbstractHandler {

    private static final Logger log = LoggerFactory.getLogger(GuestHandler.class);

    @Override
    protected boolean isHit(HandlerRequest request) {
        return request.getUserRole() == UserRole.GUEST;
    }

    @Override
    protected void handle(HandlerRequest request) {
        log.info("handle guest execute, request: {}", request);
    }
}

如果是在springboot的實際專案中,可以通過再增加一個配置類初始化將AbstractHandler各個實現類鏈起來,利用@Order確定前後順序。

@Configuration
public class InitConfigHandler implements InitializingBean {

    @Autowired
    private List<AbstractHandler> abstractHandlerList;

    @Override
    public void afterPropertiesSet() throws Exception {
        abstractHandlerList.sort(AnnotationAwareOrderComparator.INSTANCE);

        int size = abstractHandlerList.size();

        for (int i = 0; i < size - 1; i++) {
            abstractHandlerList.get(i).setNext(abstractHandlerList.get(i + 1));
        }

    }
}

這樣當需要注入使用AbstractHandler類時,預設會注入@Primary的類作為職責鏈的第一鏈。實現了職責鏈模式與springboot很好的結合。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
凍住不許走:smile:

相關文章