Я хотел бы реализовать шаблон цепочки ответственности, решающий проблему «разорванной ссылки» следующим образом:
public abstract class Handler{
private Handler m_successor;
public void setSuccessor(Handler successor)
{
m_successor = successor;
}
protected abstract boolean handleRequestImpl(Request request);
public final void handleRequest(Request request)
{
boolean handledByThisNode = this.handleRequestImpl(request);
if (m_successor != null && !handledByThisNode)
{
m_successor.handleRequest(request);
}
}
}
Похоже, подход достаточно распространенный. Но как это проверить с помощью защищенного абстрактного метода? Способы справиться с этим выглядят так:
Handler
, который реализует абстрактный метод. Это кажется плохим для тестового обслуживания. handleRequest
на одном или нескольких конкретных подклассах. Но это не кажется разумным способом организации тестов. Я читал [ 1 ], что такого рода проблема тестирования подразумевает, что дизайн неправильный, и предлагаю использовать композицию, а не наследование. Я пробую это сейчас, но кажется странным, что в рекомендуемой реализации этого шаблона есть эта проблема, но я не могу найти никаких советов по ее модульному тестированию.
ОБНОВЛЕНО: Я заменил абстрактный класс инверсией зависимостей, как показано, и теперь это легко проверить с помощью Mockito.По-прежнему похоже на цепочку ответственности ... Я что-то упускаю?
// Implement a concrete class instead
public class ChainLink {
// Successor as before, but with new class type
private ChainLink m_successor;
// New type, RequestHandler
private RequestHandler m_handler;
// Constructor, with RequestHandler injected
public ChainLink(RequestHandler m_handler) {
this.m_handler = m_handler;
}
// Setter as before, but with new class type
public void setSuccessor(ChainLink successor) {
m_successor = successor;
}
public final void handleRequest(Request request) {
boolean handledByThisNode = m_handler.handleRequest(request);
if (m_successor != null && !handledByThisNode) {
m_successor.handleRequest(request);
}
}
}