Solution: Decoupling implementation from the objects that use them.
public abstract class AbstractShape {
private DrawingProgram dp;
public abstract void draw();
public AbstractShape(DrawingProgram dp) {
this.dp = dp;
}
public void drawLine() {
this.dp.drawLine();
}
public void drawCircle() {
this.dp.drawCircle();
}
}
public class Rectangle extends AbstractShape {
public Rectangle(DrawingProgram dp) {
super(dp);
}
@Override public void draw() {
drawLine(); drawLine(); drawLine(); drawLine();
}
}
public class Circle extends AbstractShape {
public Circle(DrawingProgram dp) {
super(dp);
}
@Override public void draw() {
drawCircle();
}
}
public interface DrawingProgram {
void drawLine(); // implicitly public
void drawCircle();
}
public class DrawingProgram1 implements DrawingProgram {
@Override public void drawLine() { ... }
@Override public void drawCircle() { ... }
}
public class DrawingProgram2 implements DrawingProgram {
@Override public void drawLine() { ... }
@Override public void drawCircle() { ... }
}
public class client {
public static void main(String[] args) {
Drawing dp1 = new DrawingProgram1();
Rectangle rectangle = new Rectangle(dp1);
Drawing dp2 = new DrawingProgram2();
Circle circle = new Circle(dp2);
circle.draw();
rectangle.draw();
}
}
