依賴反轉原則
Prerequisites:
概念
英文Dependence Inversion Principle,
Abstractions should not depend on details. Details should depend on abstractions.
依賴抽象,不要依賴具體類別。
這裡的抽象包括介面,因為介面中都是抽象方法。
也跟之前提到「寫程式是針對抽象、介面而寫,而不是針對實踐方式(具體類別)而寫」,是一樣的意思。
未優化前程式碼
以下程式碼,Person收到e-mail訊息並把訊息顯示出來。
1
2
3
4
5
6
7
8
9
10
11
class Email {
void getInfo() {
System.out.println("e-mail");
}
}
class Person {
void receive(Email email) {
email.getInfo();
}
}
main主程式
1
2
3
4
5
6
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
}
}
優化思維
請問,若今天要收到Line、收到手機簡訊、收到FB的Message請問要怎麼做?是改成如下的方式嗎?那如果有100個通訊軟體,要一直寫100個receive()方法?100個參數?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person {
void receive(Email email) {
email.getInfo();
}
void receive(Line line) {
line.getInfo();
}
void receive(SMS sms) {
sms.getInfo();
}
void receive(FBMessage fbMessage) {
fbMessage.getInfo();
}
}
寫程式是針對抽象、介面而寫,而不是針對具體類別而寫。
所以我們要做一個抽象類別或介面,裡面定義抽象方法,由實作介面的類別或繼承抽象類別的子類別,去實作抽象方法。
下圖中,介面IReceive有一個抽象方法getInfo(),實作此介面的類別(Email, Line, SMS, FBMessage)都要覆寫(Override)getInfo()的方法。
下圖中,Person類別的receive()方法使用到IReceive這個介面,作為方法參數。
程式碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
interface IReceive {
void getInfo();
}
class Email implements IReceive{
@Override
public void getInfo() {
System.out.println("email");
}
}
class FBMessage implements IReceive{
@Override
public void getInfo() {
System.out.println("FB Message");
}
}
class Line implements IReceive{
@Override
public void getInfo() {
System.out.println("Line");
}
}
Person
1
2
3
4
5
class Person {
void receive(IReceive receive) {
receive.getInfo();
}
}
main主程式
1
2
3
4
5
6
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
person.receive(new Line());
person.receive(new FBMessage());
}
email
Line
FB Message