开发者

Can I avoid adapter classes when composing heterogeneous collections?

开发者 https://www.devze.com 2023-03-27 17:27 出处:网络
I need a single collection of \"processor\" classes (I happen to be using Java) that can operate on a concrete shape, say a circle.Some of the classes can operate on the abstract shape, while others r

I need a single collection of "processor" classes (I happen to be using Java) that can operate on a concrete shape, say a circle. Some of the classes can operate on the abstract shape, while others require the concrete circle class.

The problem is that, I don't know of any language or design mechanism I can use to avoid adapter classes like CircleSaver. If I can't avoid this, I'll be creating an adapter method for each processor class that requ开发者_如何转开发ires a concrete shape.

Is there a name for this problem / pattern? Is there a solution to it?

List<CircleProcessor> circleProcessors = new ArrayList<CircleProcessor>
 (Arrays.asList(new CircleDrawer(), new CircleSaver()));

interface ShapeProcessor {
    void execute(Shape circle);
}

interface CircleProcessor {
    void execute(Circle circle);
}

class CircleDrawer implements CircleProcessor {
    public void execute(Circle circle) {
        // Draw circle
    }
}

class ShapeSaver implements ShapeProcessor {
    public void execute(Shape shape) {
        shape.save();
    }
}

// Adapter method that I would love to avoid
class CircleSaver implements CircleProcessor {
    public void execute(Circle circle) {
        new ShapeSaver().execute(circle);
    }
}


After asking the question, I think I've come up with a much better version that uses generics. If there's a better solution and/or a name for this problem, please let me know!

    List<ShapeProcessor<Circle>> circleProcessors = new ArrayList<ShapeProcessor<Circle>>(
 Arrays.asList(new CircleDrawer(), new ShapeSaver<Circle>()));

public interface ShapeProcessor<T extends Shape> {
    void execute(T t);
}

public class CircleDrawer implements ShapeProcessor<Circle> {
    @Override
    public void execute(Circle circle) {
        // Draw circle
    }
}

public class ShapeSaver<T extends Shape> implements ShapeProcessor<T> {
    @Override
    public void execute(T t) {
        t.save();
    }
}


It looks a lot like the Strategy pattern. I'd make CircleProcessor an abstract class with a template method:

abstract class CircleProcessor implements ShapeProcessor {
  public final void execute(Shape shape) {
    if (!(shape instanceof Circle)) return; // ignore everything but circles

    execute((Circle) shape);
  }

  protected abstract execute(Circle circle);
}

Assuming Circle extends Shape here, but it lets you add all kinds of processors to your collection and all that support your object will do their work.

0

精彩评论

暂无评论...
验证码 换一张
取 消