Brief
S | The Single Responsibility Principle | SRP |
O | The Open/Closed Principle | OCP |
L | The Liskov Substitution Principle | LSP |
I | The Interface Segregation Principle | ISP |
D | The Dependency Inversion Principle | DIP |
Details
S for Single Responsibility Principle
The single responsibility principle (SRP) asserts that a class or module should do one thing only. If need the class do more things, seperate it into two.
O for Open/Closed Principle
Open/Closed Principle (OCP) states that software entities should be open for extension, but closed for modification. Sample as below, every time add/modify a payment type, need modify the class. it is not a good way.
// Open/Closed Principle - Bad example
public class PayHandler {
public Result<T> pay(Param param) {
if(param.getType() == "ALIPAY") {
// Handle Alipay
...
} else if(param.getType() == "WeChatPay") {
// Handle WeChatPay
...
}
}
}
Better way as below:
// Open/Closed Principle - Good example
public class PayHandler {
private Map<String, PayProcessor> processors;
public Result<T> pay(Param param) {
PayProcessor payProcessor = processors.get(param.getType());
return payProcessor.handle(param);
}
}
interface PayProcessor {
Result<T> handle(Param param);
}
public class AlipayProcessor implements PayProcessor {
...
}
public class WeChatPayProcessor implements PayProcessor {
...
}
We only need to modify the target payment processor when there is a modification requirement.
L for Liskov Substitution Principle
Liskov Substitution Principle (LSP) states that every subclass/derived class should be substitutable for their base/parent class. Explain: a Lorry class is subclass of Car class, as Car can drive, Lorry also can drive. It is defined in Java language grammar already.
I for Interface Segregation Principle
Many client specific interfaces are better than one general purpose interface. Sample as below, as WeChat don’t have the refund function.
// Interface Segregation Principle - Bad example
interface PayChannel {
void charge();
void refund();
}
class AlipayChannel implements PayChannel {
public void charge() {
...
}
public void refund() {
...
}
}
class WeChatChannel implements payChannel {
public void charge() {
...
}
public void refund() {
// Not used !!!
}
}
Better way as below:
// Interface Segregation Principle - Good example
interface PayChannel {
void charge();
}
interface RefundableChannel {
void refund();
}
class AlipayChannel implements PayChannel, RefundableChannel {
public void charge() {
...
}
public void refund() {
...
}
}
class WeChatChannel implements PayChannel {
public void charge() {
...
}
}
D for Dependency Inversion Principle
Depend upon Abstractions. Do not depend upon concretions.
// Dependency Inversion Principle - Good example
iinterface PayChannel {
void charge();
}
class WeChatChannel implements PayChannel {
public void charge() {
...
}
}
class Shop {
PayChannel payChannel;
public void setPayChannel(PayChannel w) {
payChannel = w;
}
public void makePayment() {
payChannel.pay();
}
}