자바에서는 견고한 원칙 소프트웨어 구조 설계에 적용되는 객체 지향 접근 방식입니다. 에 의해 개념화된다 로버트 C. 마틴 (밥 삼촌이라고도 함). 이 다섯 가지 원칙은 객체 지향 프로그래밍의 세계를 변화시켰고 소프트웨어 작성 방식도 변화시켰습니다. 또한 소프트웨어가 모듈식이고 이해하기 쉽고 디버깅 및 리팩터링이 용이하도록 보장합니다. 이 섹션에서는 다음 내용을 논의하겠습니다. Java의 SOLID 원칙 적절한 예를 들어 .
SOLID라는 단어의 약어는 다음과 같습니다.
- 단일 책임 원칙(SRP)
- 개방-폐쇄 원칙(OCP)
- 리스코프 대체 원칙(LSP)
- 인터페이스 분리 원칙(ISP)
- 종속성 역전 원리(DIP)
원리를 하나씩 자세히 설명해보자.
단일 책임 원칙
단일 책임 원칙은 다음과 같습니다. 모든 Java 클래스는 단일 기능을 수행해야 합니다. . 단일 클래스 매시업에서 여러 기능을 구현하면 코드가 수정되며, 수정이 필요한 경우 전체 클래스에 영향을 미칠 수 있습니다. 코드가 정확하고 코드를 쉽게 유지 관리할 수 있습니다. 예를 통해 단일 책임 원칙을 이해해 보겠습니다.
가정하다, 학생 세 가지 메소드를 갖는 클래스입니다. printDetails(),calculatePercentage(), 그리고 학생을 추가합니다(). 따라서 Student 클래스에는 학생의 세부 정보를 인쇄하고, 백분율을 계산하고, 데이터베이스를 생성하는 세 가지 책임이 있습니다. 단일 책임 원칙을 사용하면 이러한 기능을 세 가지 개별 클래스로 분리하여 원칙의 목표를 달성할 수 있습니다.
Student.java
public class Student { public void printDetails(); { //functionality of the method } pubic void calculatePercentage(); { //functionality of the method } public void addStudent(); { //functionality of the method } }
위의 코드 조각은 단일 책임 원칙을 위반합니다. 원칙의 목표를 달성하려면 단일 기능만 수행하는 별도의 클래스를 구현해야 합니다.
Student.java
public class Student { public void addStudent(); { //functionality of the method } }
PrintStudentDetails.java
public class PrintStudentDetails { public void printDetails(); { //functionality of the method } }
백분율.java
public class Percentage { public void calculatePercentage(); { //functionality of the method } }
따라서 우리는 기능을 세 개의 별도 클래스로 분리하여 단일 책임 원칙의 목표를 달성했습니다.
개방-폐쇄 원칙
애플리케이션 또는 모듈 엔터티는 메서드, 함수, 변수 등입니다. 개방형 원칙은 새로운 요구 사항에 따라 모듈은 확장을 위해 열려 있어야 하지만 수정을 위해서는 닫혀 있어야 합니다. 확장을 통해 모듈에 새로운 기능을 구현할 수 있습니다. 예를 통해 원리를 이해해보자.
가정하다, 차량정보 클래스이고 메소드가 있습니다 차량번호() 차량번호를 돌려주는 것입니다.
VehicleInfo.java
public class VehicleInfo { public double vehicleNumber(Vehicle vcl) { if (vcl instanceof Car) { return vcl.getNumber(); if (vcl instanceof Bike) { return vcl.getNumber(); } }
Truck이라는 다른 하위 클래스를 추가하려면 개방형 폐쇄 원칙을 위반하는 if 문을 하나 더 추가하면 됩니다. 하위 클래스를 추가하고 원칙의 목표를 달성하는 유일한 방법은 차량번호() 아래에 표시된 대로 방법을 사용합니다.
VehicleInfo.java
public class VehicleInfo { public double vehicleNumber() { //functionality } } public class Car extends VehicleInfo { public double vehicleNumber() { return this.getValue(); } public class Car extends Truck { public double vehicleNumber() { return this.getValue(); }
마찬가지로, 차량 클래스에서 확장되는 또 다른 하위 클래스를 만들어 더 많은 차량을 추가할 수 있습니다. 이 접근 방식은 기존 애플리케이션에 영향을 미치지 않습니다.
Liskov 대체 원칙
Liskov 대체 원칙(LSP)은 다음과 같이 도입되었습니다. 바바라 리스코프 . 상속에 적용되는 방식은 다음과 같습니다. 파생 클래스는 기본 클래스를 완전히 대체할 수 있어야 합니다. . 즉, 클래스 A가 클래스 B의 하위 유형인 경우 프로그램의 동작을 중단하지 않고 B를 A로 대체할 수 있어야 합니다.
이는 공개-닫기 원칙을 확장하고 슈퍼클래스와 해당 하위 유형의 동작에도 중점을 둡니다. 달리 해야 할 강력한 이유가 없는 한 속성을 보존하도록 클래스를 설계해야 합니다. 예를 통해 원리를 이해해보자.
Student.java
public class Student { private double height; private double weight; public void setHeight(double h) { height = h; } public void setWeight(double w) { weight= w; } ... } public class StudentBMI extends Student { public void setHeight(double h) { super.setHeight(h); super.setWeight(w); } public void setWeight(double h) { super.setHeight(h); super.setWeight(w); } }
위의 클래스는 StudentBMI 클래스에 키와 몸무게가 동일해야 한다는 추가 제약이 있기 때문에 Liskov 대체 원칙을 위반했습니다. 따라서 Student 클래스(기본 클래스)는 StudentBMI 클래스(파생 클래스)로 대체될 수 없습니다.
안드로이드의 사과 이모티콘
따라서 Student 클래스를 StudentBMI 클래스로 대체하면 예기치 않은 동작이 발생할 수 있습니다.
인터페이스 분리 원칙
원리는 더 큰 인터페이스가 더 작은 인터페이스로 분할된다는 것입니다. 구현 클래스는 필요한 메소드만 사용하기 때문입니다. 우리는 클라이언트가 사용하고 싶지 않은 방법을 사용하도록 강요해서는 안 됩니다.
인터페이스 분리 원칙의 목표는 단일 책임 원칙과 유사합니다. 예를 통해 원리를 이해해보자.
다음과 같은 인터페이스를 생성했다고 가정합니다. 변환 세 가지 방법을 가지고 intToDouble(), intToChar(), 그리고 charToString() .
public interface Conversion { public void intToDouble(); public void intToChar(); public void charToString(); }
위의 인터페이스에는 세 가지 방법이 있습니다. intToChar() 메소드만 사용하려는 경우 단일 메소드를 구현할 수 없습니다. 문제를 극복하기 위해 원칙에 따라 인터페이스를 세 개의 별도 인터페이스로 분할할 수 있습니다.
public interface ConvertIntToDouble { public void intToDouble(); } public interface ConvertIntToChar { public void intToChar(); } public interface ConvertCharToString { public void charToString(); }
이제 필요한 방법만 사용할 수 있습니다. 정수를 double로, 문자를 문자열로 변환하고 싶다면 다음 메소드만 사용한다고 가정합니다. intToDouble() 그리고 charToString().
public class DataTypeConversion implements ConvertIntToDouble, ConvertCharToString { public void intToDouble() { //conversion logic } public void charToString() { //conversion logic } }
종속성 반전 원리
원칙에 따르면 구체적인 구현 대신 추상화(추상 클래스 및 인터페이스)를 사용해야 합니다. 상위 수준 모듈은 하위 수준 모듈에 의존해서는 안 되지만 둘 다 추상화에 의존해야 합니다. 추상화가 세부 사항에 의존하는 것이 아니라 세부 사항이 추상화에 의존하기 때문입니다. 소프트웨어를 분리합니다. 예를 통해 원리를 이해해보자.
public class WindowsMachine { //functionality }
Windows에서 작업할 키보드와 마우스가 없다면 가치가 있습니다. 이 문제를 해결하기 위해 클래스의 생성자를 만들고 키보드와 모니터의 인스턴스를 추가합니다. 인스턴스를 추가한 후 클래스는 다음과 같습니다.
public class WindowsMachine { public final keyboard; public final monitor; public WindowsMachine() { monitor = new monitor(); //instance of monitor class keyboard = new keyboard(); //instance of keyboard class } }
이제 키보드와 마우스를 사용하여 Windows 시스템에서 작업할 수 있습니다. 하지만 우리는 여전히 문제에 직면해 있습니다. new 키워드를 사용하여 세 클래스를 서로 긴밀하게 결합했기 때문입니다. 클래스 Windows 컴퓨터를 테스트하는 것은 어렵습니다.
코드를 느슨하게 결합하기 위해 Keyboard 인터페이스와 이 키워드를 사용하여 키보드에서 WindowsMachine을 분리합니다.
키보드.자바
public interface Keyboard { //functionality }
WindowsMachine.java
public class WindowsMachine { private final Keyboard keyboard; private final Monitor monitor; public WindowsMachine(Keyboard keyboard, Monitor monitor) { this.keyboard = keyboard; this.monitor = monitor; } }
위 코드에서는 종속성 주입을 사용하여 WindowsMachine 클래스에 키보드 종속성을 추가했습니다. 따라서 우리는 클래스를 분리했습니다.
왜 SOLID 원칙을 사용해야 합니까?
- 다른 코드 블록에 영향을 주지 않고 코드 블록을 변경할 수 있도록 종속성을 줄입니다.
- 디자인을 더 쉽고 이해하기 쉽게 만들기 위한 원칙입니다.
- 원칙을 사용함으로써 시스템은 유지 관리, 테스트, 확장 및 재사용이 가능합니다.
- 이는 소프트웨어의 잘못된 설계를 방지합니다.
다음 번에 소프트웨어를 설계할 때 이 5가지 원칙을 염두에 두십시오. 이러한 원칙을 적용하면 코드가 훨씬 더 명확해지고 테스트 가능하며 확장 가능해집니다.