Last active
April 5, 2021 15:51
-
-
Save garudareiga/df9f7250c484983a584c to your computer and use it in GitHub Desktop.
SOLID Design Principles in Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Switch { | |
private Engine engine; | |
private boolean on; | |
public Switch(Engine engine) { | |
this.engine = engine; | |
this.on = false; | |
} | |
public boolean switchOn() { | |
return this.on; | |
} | |
public void flip() { | |
if (switchOn()) { this.on = false; engine.off(); } | |
else { this.on = true; engine.on(); } | |
} | |
} | |
// The Switch class is dependent on the Engine class which violates | |
// dependency inversion principle. It is tightly coupled with the Engine | |
// class, not reusable with any other objects. It can be designed as follows: | |
// High Level Classes (Switch) -> Abstraction Layer (SwitchClient) -> Low Level Classes (Engine) | |
public interface AbstractSwitch { | |
public boolean getState(); | |
public void flip(); | |
} | |
public interface SwitchClient { | |
public void on(); | |
public void off(); | |
} | |
public class Switch implements AbstractSwitch { | |
private SwitchClient client; | |
private boolean on; | |
public Switch(SwitchClient client) { | |
this.client = client; | |
} | |
public boolean getState() { | |
return this.on; | |
} | |
public void flip() { | |
if (getState()) { this.on = false; client.off(); } | |
else { this.on = true; client.on(); } | |
} | |
} | |
public class Engine implements SwitchClient { | |
public void on() { | |
System.out.println("Engine is on!"); | |
} | |
public void off() { | |
System.out.println("Engine is off!"); | |
} | |
} | |
Engine engine = new Engine(); | |
Switch switch = new Switch(engine); | |
switch.flip(); | |
switch.flip(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface IWorker { | |
public void work(); | |
public void eat(); | |
} | |
class Worker implements IWorker { | |
@Overwrite public void work() { | |
// Code | |
} | |
@Overwrite public void eat() { | |
// Code | |
} | |
} | |
// If we need support the new Robot class, we can split the IWorker interface as foolows: | |
interface IWorkable { | |
public void work(); | |
} | |
interface IFeedable { | |
public void eat(); | |
} | |
interface IWorker extends IWorkable, IFeedable {} | |
class Worker implements IWorker { | |
@Overwrite public void work() { | |
// Code | |
} | |
@Overwrite public void eat() { | |
// Code | |
} | |
} | |
class Robot implements IWorkable { | |
@Overwrite public void work() { | |
// Code | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Bird { | |
public void eat() {} | |
public void fly() {} | |
} | |
class Raven extends Bird {} | |
class Ostrich extends Bird { | |
fly() { throw new UnsupportedOperationException(); } | |
} | |
List<Bird> birds = new ArrayList<Bird>(); | |
birds.add(new Bird()); | |
birds.add(new Raven()); | |
birds.add(new Ostrich()); | |
for (Bird b : birds) { b.fly(); } | |
// The above code throws exception when an Ostrich instance is passed. | |
// The sub type Ostrich is not replaceable for the super type Bird. | |
// It can be designed as follows: | |
class Bird { | |
public void eat() {} | |
} | |
class FlyBird extends Bird { | |
public void fly(); | |
} | |
class NonFlyBird extends Bird {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class EmailSender { | |
public void sendEmail(Object emailData, String formatType) { | |
String rContent = null; | |
if (formatType.equalsIgnoreCase("HTML")) { | |
rContent = renderInHtml(emailData); | |
} else if (formatType.equalsIgnoreCase("TEXT")) { | |
rContent = renderInText(emailData); | |
} | |
sendEmail(rContent); | |
} | |
private void sendEmail(String rContent) { | |
// Code | |
} | |
public String renderInHtml(Object emailData) { | |
// Code | |
} | |
public String renderInText(Object emailData) { | |
// Code | |
} | |
} | |
// If we need support JSON format, we need modify the existing code which violates the principle. | |
// It can be designed as follows for good extension: | |
public class EmailSender { | |
public void sendEmail(Object emailData, IReader render) { | |
String rContent = null; | |
rContent = render.render(emailData); | |
sendEmail(rContent); | |
} | |
private void sendEmail(String rContent) { | |
// Code | |
} | |
} | |
public interface IRender { | |
public String render(Object data); | |
} | |
public class HtmlRender implements IRender { | |
@Override public String render(Object data) { | |
// Code | |
} | |
} | |
public class TextRender implements IRender { | |
@Override public String render(Object data) { | |
// Code | |
} | |
} | |
public class JsonRender implements IRender { | |
@Override public String render(Object data) { | |
// Code | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ServerConnectionManager { | |
public void createConnection(String host, String path, String port) { | |
// Code | |
} | |
public void sendRequest(Object request) { | |
// Code | |
} | |
} | |
// The above class provides two operations: make a connection and send a request. | |
// Two responsibilities are mixed up. It can be designed as follows: | |
public class ServerConnectionManager { | |
public void createConnection(String host, String path, String port) { | |
// Code | |
} | |
} | |
public class ServerConnection { | |
public void sendRequest(Object request) { | |
// Code | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment