java 调度设计模式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3672091/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
dispatch design pattern?
提问by Jason S
Suppose I have a class hierarchy in Java:
假设我在 Java 中有一个类层次结构:
interface Item { ... };
class MusicBox implements Item { ... };
class TypeWriter implements Item { ... };
class SoccerBall implements Item { ... };
and I have another class in the same package:
我在同一个包中有另一个类:
class SpecialItemProcessor {
public void add(Item item)
{
/* X */
}
}
where I want to do something different for each item type, but I don't want to define that action in the different Item
classes (MusicBox
, TypeWriter
, SoccerBall
).
我想为每个项目类型做一些不同的事情,但我不想在不同的Item
类 ( MusicBox
, TypeWriter
, SoccerBall
) 中定义该操作。
One way to handle this is:
处理这种情况的一种方法是:
class SpecialItemProcessor {
public void add(Item item)
{
if (item instanceof MusicBox)
{
MusicBox musicbox = (MusicBox)item;
... do something ...
}
else if (item instanceof MusicBox)
{
TypeWriter typewriter = (TypeWriter)item;
... do something ...
}
else if (item instanceof SoccerBall)
{
SoccerBall soccerball = (SoccerBall)item;
... do something ...
}
else
{
... do something by default ...
}
}
}
This works but it seems really clunky. Is there a better way to do this, when I know of special cases?(obviously if Item
contains a method doSomethingSpecial
then I can just call that item's method without caring what type it is, but if I don't want that differentiation to occur within the item itself how do I deal with it?)
这有效,但看起来很笨重。当我知道特殊情况时,有没有更好的方法来做到这一点?(显然,如果Item
包含一个方法,doSomethingSpecial
那么我可以只调用该项目的方法而不用关心它是什么类型,但如果我不希望在项目本身内发生这种差异,我该如何处理?)
采纳答案by Jason S
I think I'm going to use the idea of inversion of control and the visitor pattern:
我想我将使用控制反转和访问者模式的想法:
interface Item {
public void accept(Visitor visitor);
...
public interface Visitor {
public void visit(Item item);
}
}
class MusicBox implements Item {
public interface Visitor extends Item.Visitor {
public void visitMusicBox(MusicBox item);
}
...
@Override public accept(Item.Visitor visitor)
{
if (visitor instanceof MusicBox.Visitor)
{
((MusicBox.Visitor)visitor).visitMusicBox(this);
}
}
}
class TypeWriter implements Item {
public interface Visitor extends Item.Visitor {
public void visitTypeWriter(TypeWriter item);
}
...
@Override public accept(Item.Visitor visitor)
{
if (visitor instanceof TypeWriter.Visitor)
{
((TypeWriter.Visitor)visitor).visitTypeWriter(this);
}
}
}
class SoccerBall implements Item {
public interface Visitor extends Item.Visitorr {
public void visitSoccerBall(SoccerBall item);
}
...
@Override public accept(Item.Visitor visitor)
{
if (visitor instanceof SoccerBall.Visitor)
{
((SoccerBall.Visitor)visitor).visitSoccerBall(this);
}
}
}
and then do the following, which at least reduces the instanceof
to one check per add()
call:
然后执行以下操作,这至少将instanceof
每次add()
调用减少到一次检查:
class SpecialItemProcessor
implements
MusicBox.Visitor,
TypeWriter.Visitor,
SoccerBall.Visitor,
Item.Visitor
{
public void add(Item item)
{
item.accept(this);
}
@Override public void visitMusicBox(MusicBox item)
{
...
}
@Override public void visitTypeWriter(TypeWriter item)
{
...
}
@Override public void visitSoccerBall(SoccerBall item)
{
...
}
@Override public void visit(Item item)
{
/* not sure what if anything I should do here */
}
}
回答by Affe
In Java you can do multiple dispatch with a visitor(-like) pattern. The Item implementations don't need to contain the processing logic, they just need an accept()
type of method.
在 Java 中,您可以使用访问者(类似)模式进行多次分派。Item 实现不需要包含处理逻辑,它们只需要一种accept()
方法。
public interface Item {
/** stuff **/
void processMe(ItemProcessor processor);
}
public interface ItemProcessor {
void process(MusicBox box);
void process(SoccerBall ball);
//etc
}
public class MusicBox implements Item {
@Override
public void processMe(ItemProcessor processor) {
processor.process(this);
}
}
public class ItemAddingProcessor implements ItemProcessor {
public void add(Item item) {
item.processMe(this);
}
@Override
public void process(MusicBox box) {
//code for handling MusicBoxes
//what would have been inside if (item instanceof MusicBox) {}
}
//etc
}
回答by Cherish
Why not define some callback function to Item interface?
为什么不给Item接口定义一些回调函数呢?
public Interface Item {
void onCallBack();
}
Then in each class that implements Item, such as MusicBox, it should implement the callback function.
那么在每个实现Item的类中,比如MusicBox,都应该实现回调函数。
public class MusicBox {
@override
public void onCallBack() {
// business logic
...
...
}
}
Then you could create a dispatcher, which you name is "SpecialItemProcessor".
然后您可以创建一个调度程序,您将其命名为“SpecialItemProcessor”。
public SpecialItemProcessor {
private final Item _item;
public SpecialItemProcessor(Item item) {
_item = item;
}
public dispatch() {
_item.onCallBack()
}
}
And then, in the Client class which contains the SpecialItemProcessor could just call the method, like:
然后,在包含 SpecialItemProcessor 的 Client 类中可以调用该方法,例如:
public void XXXX() {
....
SpecialItemProcessor specialItemProcessor = new SpecialItemProcessor(new MusicBox());
specialItemProcessor.dispatch();
....
}
Actually, in C++, this is Dynamic Binding. And this is why pure abstract class exists...
实际上,在 C++ 中,这就是动态绑定。这就是为什么存在纯抽象类的原因......
回答by Baltasarq
You could create a bridge pattern for Item, in which the other side were the associated processes to do when add() is called. You could also add a factory method to the mix.
您可以为 Item 创建桥接模式,其中另一端是调用 add() 时要执行的关联进程。您还可以将工厂方法添加到组合中。
class SpecialItemProcessor {
public void add(Item item)
{
Process p = Item.createCorrespondingProcessor( p );
p.doWhenAddin();
}
}
Hope this helps.
希望这可以帮助。