JAVA의 견고한 원칙

12878 단어 java
SOLID는 소프트웨어 개발과 관련된 객체 지향 설계 개념입니다.

솔리드는 약자입니다.

단일 책임 원칙,
개폐 원칙,
Liskov 대체 원리,
인터페이스 분리 원리 및
종속성 역전 원리

단일 책임 원칙



클래스는 한 가지 일만 수행해야 합니다. 즉, 각 클래스는 시스템의 단일 기능을 담당해야 합니다.

SRP를 따르지 않는 예:

class Vehicle{
    public void calculateValue(){...}
    public void printDetails(){...}
    public void addVehicleInDb(){...}
}


클래스Vehicle에는 세 가지 별도의 작업이 있습니다. SRP에 따르면 단일 책임으로 여러 클래스로 분리되어야 합니다.

개폐 원칙



클래스는 확장에는 열려 있지만 수정에는 닫혀 있어야 합니다.

아래 클래스 방법을 고려하십시오VehicleCalculations.

public class VehicleCalculations {
    public double calculateValue(Vehicle v) {
        if (v instanceof Car) {
            return v.getValue() * 0.8;
        if (v instanceof Bike) {
            return v.getValue() * 0.5;

    }
}


이제 Truck라는 다른 하위 클래스를 추가하려면 개방형 폐쇄 원칙에 위배되는 또 다른 if 문을 추가하여 위의 메서드를 수정해야 합니다.
더 나은 접근 방식은 하위 클래스CarTruckcalculateValue() 메서드를 재정의하는 것입니다.

public class Vehicle {
    public double calculateValue() {...}
}
public class Car extends Vehicle {
    public double calculateValue() {
        return this.getValue() * 0.8;
}
public class Truck extends Vehicle{
    public double calculateValue() {
        return this.getValue() * 0.9;
}


Liskov 대체 원리



코드를 손상시키지 않고 상위 클래스의 객체를 하위 클래스의 객체로 쉽게 대체해야 함을 알려줍니다.
Rectangle 기본 클래스와 Square 파생 클래스의 예를 고려하십시오.

public class Rectangle {
    private double height;
    private double width;
    public void setHeight(double h) { height = h; }
    public void setWidht(double w) { width = w; }
    ...
}
public class Square extends Rectangle {
    public void setHeight(double h) {
        super.setHeight(h);
        super.setWidth(h);
    }
    public void setWidth(double w) {
        super.setHeight(w);
        super.setWidth(w);
    }
}


위의 클래스는 기본 클래스Rectangle를 파생 클래스Square로 대체할 수 없기 때문에 LSP를 따르지 않습니다. Square 클래스에는 추가 제약 조건이 있습니다. 즉, 높이와 너비가 동일해야 합니다. 따라서 Rectangle 클래스를 Square 클래스로 대체하면 예기치 않은 동작이 발생할 수 있습니다.

인터페이스 분리 원리



ISP(인터페이스 분리 원칙)는 클라이언트가 사용하지 않는 인터페이스 멤버에 의존하도록 강요해서는 안 된다고 명시합니다. 즉, 어떤 클라이언트도 자신과 무관한 인터페이스를 구현하도록 강요하지 마십시오.

차량용 인터페이스와 Bike 클래스가 있다고 가정합니다.

public interface Vehicle {
    public void drive();
    public void stop();
    public void refuel();
    public void openDoors();
}
public class Bike implements Vehicle {

    // Can be implemented
    public void drive() {...}
    public void stop() {...}
    public void refuel() {...}

    // Can not be implemented
    public void openDoors() {...}
}


보시다시피 자전거에는 문이 없기 때문에 Bike 클래스가 openDoors() 메서드를 구현하는 것은 이치에 맞지 않습니다! 이 문제를 해결하기 위해 ISP는 인터페이스를 여러 개의 작은 응집력 있는 인터페이스로 분할하여 어떤 클래스도 인터페이스를 강제로 구현하지 않도록 하고 따라서 필요하지 않은 메서드를 제안합니다.

종속성 역전 원칙



DIP(Dependency Inversion Principle)는 구체적인 구현(클래스) 대신 추상화(인터페이스 및 추상 클래스)에 의존해야 한다고 명시합니다. 추상화는 세부 사항에 의존해서는 안 됩니다. 대신 세부 사항은 추상화에 의존해야 합니다.

아래 예를 고려하십시오. 구체적인 Car 클래스에 의존하는 Engine 클래스가 있습니다. 따라서 DIP를 준수하지 않습니다.

public class Car {
    private Engine engine;
    public Car(Engine e) {
        engine = e;
    }
    public void start() {
        engine.start();
    }
}
public class Engine {
   public void start() {...}
}


지금은 코드가 작동하지만 다른 엔진 유형, 예를 들어 디젤 엔진을 추가하려면 어떻게 해야 할까요? 이렇게 하려면 Car 클래스를 리팩토링해야 합니다.
그러나 추상화 계층을 도입하여 이를 해결할 수 있습니다. Car 에 직접 의존하는 대신 Engine 인터페이스를 추가해 보겠습니다.

public interface Engine {
    public void start();
}


이제 Engine 인터페이스를 구현하는 모든 유형의 엔진을 Car 클래스에 연결할 수 있습니다.

public class Car {
    private Engine engine;
    public Car(Engine e) {
        engine = e;
    }
    public void start() {
        engine.start();
    }
}
public class PetrolEngine implements Engine {
   public void start() {...}
}
public class DieselEngine implements Engine {
   public void start() {...}
}

좋은 웹페이지 즐겨찾기