在本文中,您將學習到SOLID原則。您將獲得每個原則的深入了解以及Java程式碼示例。
SOLID原則是一組在物件導向程式設計中使用的五個設計原則。遵循這些原則將幫助您開發堅固的軟體。它們將使您的程式碼更有效率、更具可讀性並易於維護。
SOLID是一個缩寫,代表:
- 單一責任原則
- 開閉原則
- 里氏replace原则
- 介面分割原則
- 依賴倒置原則
單一責任原則
單一責任原則指出,每個類別必須具有單一、集中的責任,一個變化的單一原因。
public class Employee{
public String getDesignation(int employeeID){ // }
public void updateSalary(int employeeID){ // }
public void sendMail(){ // }
}
在上面 example,the Employee
class has a few employee class-specific behaviors like getDesignation
& updateSalary
.
Additionally, it also has another method named sendMail
which deviates from the responsibility of the Employee
class.
This behavior is not specific to this class, and having it violates the single responsibility principle. To overcome this, you can move the sendMail
method to a separate class.
以下是這樣做的方法:
public class Employee{
public String getDesignation(int employeeID){ // }
public void updateSalary(int employeeID){ // }
}
public class NotificationService {
public void sendMail() { // }
}
開閉原則
根據開閉原則,元件必須對擴展开放,但对修改closed。為了理解這個原則,讓我們看一個計算圖形面積的类的例子。
public class AreaCalculator(){
public double area(Shape shape){
double areaOfShape;
if(shape instanceof Square){
// 計算正方形的面積
} else if(shape instanceof Circle){
// 計算圓形的面積
}
return areaOfShape;
}
上述例子的問題是,如果未來需要計算新型態Shape
的面積,你必须通過添加另一個else-if
條件來修改上述類。你將必須為Shape
類的每個新物件这样做。
為了克服這個問題,你可以創建一個接口,並讓每個Shape
實例化這個接口。然後,每個類都可以提供自己的實現來計算面積。這將使你的程序在未來容易擴展。
interface IAreaCalculator(){
double area();
}
class Square implements IAreaCalculator{
@Override
public double area(){
System.out.println("Calculating area for Square");
return 0.0;
}
}
class Circle implements IAreaCalculator{
@Override
public double area(){
System.out.println("Calculating area for Circle");
return 0.0;
}
}
里斯科夫replace Principle
里斯科夫replace原则表明,你必须能夠將超類物件替換為子類物件,而不影響程式的正確性。
abstract class Bird{
abstract void fly();
}
class Eagle extends Bird {
@Override
public void fly() { // 一些實作 }
}
class Ostrich extends Bird {
@Override
public void fly() { // 假的實作 }
}
在上述示例中,Eagle
類別和 Ostrich
類別都擴展了 Bird
類別並覆写了 fly()
方法。然而,由於 Ostrich
類別不能飛翔,因此它必須提供一個模擬實現,這就導致我们不能將 Bird
類別物件替換成它,因為它的行為不一樣。
這違反了 Liskov 替代原則。為了解決這個問題,我們可以創建一個分離的飛翔鳥類類別,並讓 Eagle
類別擴展它,而其餘的鳥類可以擴展另一個不包含任何 fly
行為的類別。
abstract class FlyingBird{
abstract void fly();
}
abstract class NonFlyingBird{
abstract void doSomething();
}
class Eagle extends FlyingBird {
@Override
public void fly() { // 一些實現 }
}
class Ostrich extends NonFlyingBird {
@Override
public void doSomething() { // 一些實現 }
}
接口隔离原则
根據接口隔离原則,您應該建立小型、集中的接口,不會強制客戶實現它們不需要的行為。
一個直觀的例子是擁有一個計算形狀面積和體積的接口。
interface IShapeAreaCalculator(){
double calculateArea();
double calculateVolume();
}
class Square implements IShapeAreaCalculator{
double calculateArea(){ // 計算面積 }
double calculateVolume(){ // 模擬實現 }
}
這個問題的解決方法是,如果一個 Square
形狀實現這個接口,那麼它就被迫實現 calculateVolume()
方法,這對於它來說是不必要的。
另一方面,一個 Cube
能夠實現兩者。為了解決這問題,我們可以將接口隔離,並有兩個分開的接口:一個用於計算面積,另一個用於計算體積。這將讓每個形狀自行決定要實現什麼。
interface IAreaCalculator {
double calculateArea();
}
interface IVolumeCalculator {
double calculateVolume();
}
class Square implements IAreaCalculator {
@Override
public double calculateArea() { // 計算面積 }
}
class Cube implements IAreaCalculator, IVolumeCalculator {
@Override
public double calculateArea() { // 計算面積 }
@Override
public double calculateVolume() {// 計算體積 }
}
依賴倒置原則
在依賴倒置原則中,高层次模塊不應該依賴低层次模塊。换句话说,你必須遵循抽象化,並確保松耦合
public interface Notification {
void notify();
}
public class EmailNotification implements Notification {
public void notify() {
System.out.println("Sending notification via email");
}
}
public class Employee {
private EmailNotification emailNotification;
public Employee(EmailNotification emailNotification) {
this.emailNotification = emailNotification;
}
public void notifyUser() {
emailNotification.notify();
}
}
在給定示例中,Employee
類別直接依賴於 EmailNotification
類別,這是一個低层次模塊。這違反了依賴倒置原則。
public interface Notification{
public void notify();
}
public class Employee{
private Notification notification;
public Employee(Notification notification){
this.notification = notification;
}
public void notifyUser(){
notification.notify();
}
}
public class EmailNotification implements Notification{
public void notify(){
//透過電子郵件實現通知
}
}
public static void main(String [] args){
Notification notification = new EmailNotification();
Employee employee = new Employee(notification);
employee.notifyUser();
}
在上述示例中,我們已確保松耦合。Employee
不是依賴於任何具體實現,而是僅依賴於抽象(通知介面)。
如果我们需要更改通知模式,我們可以創建新的實現並傳遞給 Employee
。
結論
總結來說,我們在本文中通過直觀的示例覆盖了 SOLID 原則的精髓。
這些原則形成開發高度可擴展和重用應用程序的基礎。
讓我們在 LinkedIn 上聯繫吧
Source:
https://www.freecodecamp.org/news/introduction-to-solid-principles/