Suppose
a drawing application is implemented like below.
Drawer.java
Shape.java
package com.sample.model; public enum Shape { CIRCLE("circle"), SQUARE("square"), RECTANGLE("rectangle"); private Shape(String type) { this.type = type; } private String type; public String getType() { return type; } }
Drawer.java
package com.sample.util; import com.sample.model.Shape; public class Drawer { private Shape shape; public Shape getShape() { return shape; } public void setShape(Shape shape) { this.shape = shape; } public void draw() { if (Shape.CIRCLE.getType().equals(shape.getType())) { System.out.println("Drawing Circle"); } else if (Shape.RECTANGLE.getType().equals(shape.getType())) { System.out.println("Drawing Rectangle"); } else if (Shape.SQUARE.getType().equals(shape.getType())) { System.out.println("Drawing Square"); } } }
Application.java
package com.smaple.app; import com.sample.model.Shape; import com.sample.util.Drawer; public class Application { public static void main(String args[]) { Drawer drawer = new Drawer(); drawer.setShape(Shape.SQUARE); drawer.draw(); } }
Above
code breaks the design principle “Open to extension, closed to modification”.
As
per Open-closed principle, software entities such as classes, methods should be
open for extension and closed for modification. That is we can extend the
behavior of software entity, without touching the source code of the entity.
For
example, there is a class ‘ConnectionFactory’, it provides number of methods to
connect to databases like MySQL, MongoDB, Elasticsearch etc., Assume there are
number of classes using this ConnectionFactory. Even if you change single line
in ConnectionFactory class, you need to retest all the modules that are using
ConnectionFactory class. If you design your code like this, you will end up in
testing all the dependent modules often.
Open-closed
principle solved this problem in straightforward way.
Rule 1: Design a module such
that, it never change.
Rule 2: When requirements
change, extend (Inheritance) the behavior of an entity by adding new code.
Modules
that follow above two rules are open for extension and closed for modification.
Let’s
redesign the drawing application like below.
Shape.java
package com.sample.model; public interface Shape { void draw(); }
Circle.java
package com.sample.model; public class Circle implements Shape{ public void draw() { System.out.println("Drawing Circle"); } }
Square.java
package com.sample.model; public class Square implements Shape { public void draw() { System.out.println("Drawing Square"); } }
Rectangle.java
package com.sample.model; public class Rectangle implements Shape { public void draw() { System.out.println("Drawing Rectangle"); } }
Drawer.java
package com.sample.util; import com.sample.model.Shape; public class Drawer { private Shape shape; public Shape getShape() { return shape; } public void setShape(Shape shape) { this.shape = shape; } public void draw() { if (shape == null) { return; } shape.draw(); } }
Application.java
package com.smaple.app; import com.sample.model.Square; import com.sample.util.Drawer; public class Application { public static void main(String args[]) { Drawer drawer = new Drawer(); drawer.setShape(new Square()); drawer.draw(); } }
You may like
No comments:
Post a Comment