Java 使用泛型实现责任链
所以我想实现责任链,但使用泛型,有上限Java 使用泛型实现责任链,java,generics,chain-of-responsibility,Java,Generics,Chain Of Responsibility,所以我想实现责任链,但使用泛型,有上限 public abstract class Handler<C extends Command> { private Handler<? extends Command> successor; public Handler(Handler<? extends Command> successor) { this.successor = successor; } pub
public abstract class Handler<C extends Command> {
private Handler<? extends Command> successor;
public Handler(Handler<? extends Command> successor) {
this.successor = successor;
}
public final String handle(C cmd) {
if (canHandle(cmd)) {
return doHandle(cmd);
} else {
// The method doHandle(capture#3-of ? extends Command) in the type Handler<capture#3-of ? extends Command>
// is not applicable for the arguments (C)
return successor.doHandle(cmd);
}
}
protected abstract boolean canHandle(C cmd);
protected abstract String doHandle(C cmd);
}
abstract class Command {
public String getParamBase() {
return "base";
}
}
class CommandTypeOne extends Command {
public String getTypeOneParam() {
return "ParamTypeOne";
}
}
class CommandTypeTwo extends Command {
public String getTypeTwoParam() {
return "ParamTypeTwo";
}
}
公共抽象类处理程序{
私人处理程序想象一下,如果您将命令
替换为动物
(猫
和狗
的超类),会发生什么情况
succession
引用的签名表示它可以处理某些类型的动物,比如只猫。另一方面,handle()
方法的cmd
参数也表示要处理的命令可以是任何其他动物的子类型-在这里,Dog
可能是有效类型
您可以看到,没有任何东西可以保证后续处理程序能够管理特定类型的命令,因此编译器会有些生气。这里是您的处理程序类
//In your case 'C extends Command' in class declaration will be enough
public abstract class Handler<C extends Command> {
private Handler<C> successor;
public Handler(Handler<C> successor) {
this.successor = successor;
}
public final String handle(C cmd) {
if (canHandle(cmd)) {
return doHandle(cmd);
} else {
// The method doHandle(capture#3-of ? extends Command) in the type Handler<capture#3-of ? extends Command>
// is not applicable for the arguments (C)
return successor.doHandle(cmd);
}
}
protected abstract boolean canHandle(C cmd);
protected abstract String doHandle(C cmd);
//在您的情况下,类声明中的“C extends命令”就足够了
公共抽象类处理程序{
私人经办人继承人;
公共处理程序(处理程序继任者){
这个后继者=后继者;
}
公共最终字符串句柄(C cmd){
if(canHandle(cmd)){
返回doHandle(cmd);
}否则{
//类型处理程序中的方法doHandle(capture#3-of?extends命令)
//不适用于参数(C)
返回继任者.doHandle(cmd);
}
}
受保护抽象布尔canHandle(C cmd);
受保护的抽象字符串doHandle(C cmd);
}您的字段继承者可以保存一个实例,它实际上是一个处理程序
,因为只要C扩展命令
,它就可以保存所有内容。它的doHandle
方法的签名将是String doHandle(CommandTypeOne cmd)
。如果您在handle()中调用succinator.doHandle()
您将传递一个参数,该参数只保证是命令
,而不是命令类型
也许你应该看看.Producer extends-Consumer super。你可以用谷歌搜索它。在你的例子中,你的doHandle方法是一个消费者,你应该使用super而不是extends
在这种情况下,我可能不使用泛型。将命令放在C现在的位置。这允许将命令和子类型传递给处理程序链。要允许处理程序区分命令,可以使用字符串或int为命令建立id。或者可以使用instanceof允许处理程序检查命令的特定子类型。这两种解决方案都不是非常面向对象的
此时,您的命令感觉像一个数据容器,根据您的子类型具有不同的内容。在哪一行出现错误?在这种情况下是否需要使用泛型?所有扩展Command
的对象都与Command
有is-a关系。您的处理程序是否需要所有命令
是否属于同一子类型?相关问题:@gurghet您也可以看到代码中的错误,我也将其作为注释放在那里。问题是,处理程序不是同一子类型,我希望每个子类型都有一个处理程序,子类型将作为泛型传递。我希望使用泛型来避免使用instanceof和casting。谢谢链接,Mick会读到它。flex my PECS?我早就听说了。我想你说的话和Olivier Croisier说的很相似,我完全理解你的解释。但是在读了一点关于PECS的内容后,我不知道如何正确修改代码。即使我使错误消失,处理程序不是处理程序的子类型,我无法创建处理程序链…如果我错了请纠正我byt这不正是我要避免的吗?假设我们有一个处理程序,这意味着它的后续处理程序将只能根据构造函数和后续字段的签名进行处理。这是否正确让处理程序具有类似于处理程序的后续程序是否合理?如果链请求将是CommandTypeOne,那么它应该只由类型处理程序的后续程序处理,不是吗?或者我不清楚您实际想要做什么。每个处理程序都应该处理一个子类型。尝试创建一个类HandlerTypeOne扩展处理程序{……}现在看看它的构造函数。它接受Hander,就像你说的,让两个处理程序处理同一类型的请求是没有意义的。哦,我终于明白你的意思了,你要做的是使用java jenerics是不可能的。我想我已经意识到了,回答Sponiro的回答。非常感谢你的时间,先生。Handler继任者=新处理程序(null);处理程序dogHandler=新处理程序(后续);DogHandler中的方法canHandle,doHandle,handle处理Dog方法canHandle,doHandle,handle在继承者处理Cat中不确定我是否遵循。如果您的实例被声明为处理程序
,则类型变量C
将在句柄()的签名中为Dog
方法。但是如果它的后继者
字段的类型是Handler
,您就有问题了。`是的,但是为什么,它们都是动物。我看不出它们之间有多大区别,因为您的类型签名没有说“我可以处理任何动物”,而是说“我只能处理一种动物”,并且Handler
所声明的动物的确切类型可能与其继任者的不同。