调度设计模式?

发布于 2024-09-17 22:23:33 字数 1307 浏览 3 评论 0原文

假设我在 Java 中有一个类层次结构:

interface Item { ... };
class MusicBox implements Item { ... };
class TypeWriter implements Item { ... };
class SoccerBall implements Item { ... };

并且在同一个包中还有另一个类:

class SpecialItemProcessor {
    public void add(Item item)
    {
        /* X */
    }
}

我想在其中为每个项目类型执行不同的操作,但我不想在不同的 Item 类(MusicBoxTypeWriterSoccerBall)。

处理这个问题的一种方法是:

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 ...
        }
    }
}

这可行,但看起来确实很笨重。 当我知道特殊情况时,是否有更好的方法来做到这一点?(显然,如果 Item 包含方法 doSomethingSpecial 那么我可以调用该项目的方法而不关心它是什么类型,但如果我不希望在项目本身内发生这种差异,我该如何处理它?)

Suppose I have a class hierarchy in 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).

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?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

╰◇生如夏花灿烂 2024-09-24 22:23:33

在 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
}

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.

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
}
芯好空 2024-09-24 22:23:33

我想我将使用控制反转的思想和访问者模式

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);
      }
   }
}

和然后执行以下操作,这至少将 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 */
    }
 }

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:

 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 */
    }
 }
忘你却要生生世世 2024-09-24 22:23:33

为什么不为 Item 接口定义一些回调函数?

public Interface Item {
  void onCallBack();
}

然后在每个实现Item的类中,例如MusicBox,都应该实现回调函数。

public class MusicBox {
  @override
  public void onCallBack() {
    // business logic
    ...
    ...  
  }
}

然后您可以创建一个调度程序,您将其命名为“SpecialItemProcessor”。

public SpecialItemProcessor {
  private final Item _item;

  public SpecialItemProcessor(Item item) {
    _item = item;
  }

  public dispatch() {
    _item.onCallBack()
  }
}

然后,在包含 SpecialItemProcessor 的 Client 类中可以调用该方法,例如:

public void XXXX() {
  ....
  SpecialItemProcessor specialItemProcessor = new SpecialItemProcessor(new MusicBox());
  specialItemProcessor.dispatch();
  ....
}

实际上,在 C++ 中,这就是动态绑定。这就是纯抽象类存在的原因......

Why not define some callback function to Item interface?

public Interface Item {
  void onCallBack();
}

Then in each class that implements Item, such as MusicBox, it should implement the callback function.

public class MusicBox {
  @override
  public void onCallBack() {
    // business logic
    ...
    ...  
  }
}

Then you could create a dispatcher, which you name is "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:

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...

樱娆 2024-09-24 22:23:33

您可以为 Item 创建一个桥接模式,其中另一端是调用 add() 时要执行的关联进程。您还可以添加工厂方法。

class SpecialItemProcessor {
  public void add(Item item)
  {
     Process p = Item.createCorrespondingProcessor( p );
     p.doWhenAddin();
  }
}

希望这有帮助。

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.

class SpecialItemProcessor {
  public void add(Item item)
  {
     Process p = Item.createCorrespondingProcessor( p );
     p.doWhenAddin();
  }
}

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文