我有一个简化的设计如下(基本上是一堆处理程序来处理两种不同类型的请求:eventrequest和speechrequest)。下面是伪代码:

class SpeechRequest {sessionId: String; slot: String}
class EventRequest {sessionId: String; event: String}

class SpeechRequestHandler;
class EventRequestHandler;

class SpeechRequestHandler[A/B/C] extends SpeechRequestHandler {
    - handle(request: SpeechRequest) {
        doSt(request.slot)
    }
}

class EventRequestHandler[A/B/C] extends EventRequestHandler {
    - handle(request: EventRequest) {
        doSt(request.event)
    }
}

有两个不同的分派器可以为每种类型的请求找到适当的处理程序,并将它们转发给要处理的处理程序:
class SpeechDispatcher {
    - handle(request: SpeechRequest) {
        handler: SpeechRequestHandler = findHandlerToHandle(request);
        handler.handle(request);
    }
}

class EventDispatcher {
    - handle(request: EventRequest) {
        handler: EventRequestHandler = findHandlerToHandle(request);
        handler.handle(request);
    }
}

现在,我想重构并创建一个基/公共类。很自然,我想到了这个:
class Request {sessionId: String}
class SpeechRequest extends Request {slot: String}
class EventRequest extends Request {event: String}

class RequestHandler {
    - canHandleRequest(Request): bool
    - handle(Request)
}

class SpeechRequestHandler extends RequestHandler {
    - canHandleRequest(request: Request): bool = request instanceof SpeechRequest
}

class EventRequestHandler extends RequestHandler {
    - canHandleRequest(request: Request): bool = request instanceof EventRequest
}

class SpeechRequestHandler[A/B/C] extends SpeechRequestHandler {
    - handle(Request: request) {
        //need to cast to specific type to extract a certain fields to do some operation
        //!! I feel something is not right because of that
        speechRequest:SpeechRequest = (SpeechRequest)request;
        doSt(speechRequest.slot)

        //other operation can work with base Request object; so it's OK
    }
}

class EventRequestHandler[A/B/C] extends EventRequestHandler {
    - handle(Request: request) {
        eventRequest:EventRequest = (EventRequest)request;
        doSt(eventRequest.event)

        //other operation can work with base Request object; so it's OK
    }
}

事实上,对于所有speechrequesthandler[a/b/c]:handle函数,我现在需要将请求对象具体地转换为(speechrequest)对象:speechrequest:speechrequest=(speechrequest)request;
我觉得我的设计有缺陷。如果每个speechrequesthandler都需要将对象强制转换为(speechrequest),以便我可以处理这些信息,这是否意味着在这种情况下重构基类没有意义?
请你提出一个更好的方式或设计模式来处理这个干净。
谢谢您。

最佳答案

如果你想保持类型安全,你可以做这种事情与双重调度。见https://en.wikipedia.org/wiki/Double_dispatch
看起来你想要这样的东西:

interface HandlerSet{
    SpeechHandler getSpeechHandler(Request request);
    EventHandler getEventHandler(Request request);
}

abstract Request {
    ... common stuff ...
    abstract handleWith(HandlerSet handlers);
}
class SpeechRequest extends Request {
    sessionId: String; slot: String
    handleWith(HandlerSet handlers) {
        return handlers.getSpeechHandler(this).handle(this);
    }
}
class EventRequest extends Request {
    sessionId: String; event: String
    handleWith(HandlerSet handlers) {
        return handlers.getEventHandler(this).handle(this);
    }
}

关于java - OOP设计-何时具有通用基类[缺陷设计?],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48431941/

10-09 03:24