Solution: Decoupling implementation from the objects that use them.
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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(); } } |
1 2 3 4 5 6 7 8 | public class Rectangle extends AbstractShape { public Rectangle(DrawingProgram dp) { super (dp); } @Override public void draw() { drawLine(); drawLine(); drawLine(); drawLine(); } } |
1 2 3 4 5 6 7 8 | public class Circle extends AbstractShape { public Circle(DrawingProgram dp) { super (dp); } @Override public void draw() { drawCircle(); } } |
1 2 3 4 | public interface DrawingProgram { void drawLine(); // implicitly public void drawCircle(); } |
1 2 3 4 | public class DrawingProgram1 implements DrawingProgram { @Override public void drawLine() { ... } @Override public void drawCircle() { ... } } |
1 2 3 4 | public class DrawingProgram2 implements DrawingProgram { @Override public void drawLine() { ... } @Override public void drawCircle() { ... } } |
1 2 3 4 5 6 7 8 9 10 11 | 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(); } } |