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.
精彩评论