简体   繁体   中英

Can I avoid adapter classes when composing heterogeneous collections?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM