与子项共享基类型列表

Mic*_*ann 5 java oop

我有一个基类ShapeManager,其中包含我想要的形状列表 enumerate().然后有一个专门化ColoredShapeManager想要处理专门的ColoredShapes而不是Shapes:

+----------------+      +-------------------------------------+
| Shape          |      | ShapeManager                        |
|----------------|      |-------------------------------------|
| + id: int      |      | # shapes: List<Shape>               |
|                |      |                                     |
|                |      | + ShapeManager() {                  |
|                |      |     shapes.add(new Shape());        |
|                |      |   }                                 |
|                |      |                                     |
|                |      | + abstract void enumerate() {       |
|                |      |     for (Shape s: shapes) {         |
|                |      |        // use s                     |
|                |      |     }                               |
|                |      |   }                                 |
+----------------+      +-------------------------------------+
         ^                              ^
         |                              |
         +                              +
+----------------+      +-------------------------------------+
| ColoredShape   |      | ColoredShapeManager                 |
|----------------|      |-------------------------------------|
| + color: int   |      | + ColoredShapeManager() {           |
|                |      |     shapes.add(new ColoredShape()); |
|                |      |   }                                 |
|                |      |                                     |
|                |      | + abstract void enumerate() {       |
|                |      |     for (Shape s: shapes) {         |
|                |      |       // use (ColoredShaped) s      |
|                |      |       // will fail for Shapes       |
|                |      |     }                               |
|                |      |   }                                 |
+----------------+      +-------------------------------------+
Run Code Online (Sandbox Code Playgroud)

我不确定ShapeManager是否应该shapes: List<Shape>与它的孩子共享这似乎有缺陷,因为ColoredShapeManager.enumerate()想要处理ColoredShapes.因此它会转换元素,但是一些元素(由基类添加的元素)是类型的,Shape并且转换会失败.

那是:

  • 两种类型的形状最终都在列表中shapes.
  • enumerate()在孩子经理应该有权访问ColoredShape.

我是否应该拆分列表并在两个管理器中创建私人列表?然后在子项中枚举只会迭代"它"类型的形状并enumerate()在开始/结束时调用父项.

San*_*rma 6

您可以将形状类型添加为经理类的"类型参数".所以基本上,ColoredShapeManager可以扩展ShapeManager<ColoredShape>,这T将是您的内部List数据结构的类型.另外,如果你ColoredShapeManager没有做任何特定的事情ColoredShapes,我会争辩说它甚至不需要新的课程.但是,这又取决于您构建应用程序/设计的方式.


S.D*_*.D. 2

为什么不分离出行为泛化容器呢?

容器:

public class ShapeManager<T extends Shape> {
    private List<T> shapeList;

    public void processShapes(ShapeProcessor processor){
        for (T shape : shapeList){
            processor.process(shape);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

和行为(您还可以有一个工厂类来提供不同的实现):

public class ShapeProcessor {

    public void process(Shape shape) {

    }

    public void process(ColoredShape shape){

    }
}
Run Code Online (Sandbox Code Playgroud)

或者,进入完整的访客模式

public abstract class Shape {
    public void accept(ShapeProcessor processor){
        processor.process(this);
    }
}

public interface ShapeProcessor {
    public void process(Shape shape);
    public void process(ColoredShape shape);
}

public class ShapeManager {
    private List<Shape> shapeList;

    public void processShapes(ShapeProcessor processor){
        for (Shape shape : shapeList){
            shape.accept(processor);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这允许枚举多种形状,并应用不同类型的处理方法,这也来自不同类型的形状处理器。经理不关心他们中的任何一个。