项目作者: beomjo

项目描述 :
Learn more about SOLID object oriented design
高级语言: Java
项目地址: git://github.com/beomjo/SOLID.git
创建时间: 2019-09-19T05:47:54Z
项目社区:https://github.com/beomjo/SOLID

开源协议:

下载


SOLID

S(단일 책임 원칙)
한 클래스는 하나의 책임만 가져야 하고,
클래스는 자신의 이름이 나타내는 일 하나만을 해야합니다.

  1. public class Vehicle {
  2. private final int maxFuel;
  3. private int remainingFuel;
  4. public Vehicle(int maxFuel) {
  5. this.maxFuel = maxFuel;
  6. remainingFuel = maxFuel;
  7. }
  8. //연료 충전은 Vehicle의 responsibility가 아니므로 SRC에 위반
  9. public void reFuel() {
  10. remainingFuel = maxFuel;
  11. }
  12. public int getMaxFuel() {
  13. return maxFuel;
  14. }
  15. public int getRemainingFuel() {
  16. return remainingFuel;
  17. }
  18. public void setRemainingFuel(int remainingFuel) {
  19. this.remainingFuel = remainingFuel;
  20. }
  21. public void accelerate() {
  22. remainingFuel--;
  23. }
  24. }

#
O(개방-폐쇄 원칙)
소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 합니다.
즉 ,기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계가 되어야 합니다

violation

  1. public enum DrivingMode {
  2. SPORT, COMFORT
  3. }
  1. public class Drive {
  2. private Vehicle vehicle;
  3. public Drive(final Vehicle vehicle) {
  4. this.vehicle = vehicle;
  5. }
  6. public void changeDrivingMode(final DrivingMode drivingMode){
  7. switch (drivingMode){
  8. case SPORT:
  9. vehicle.setPower(500);
  10. vehicle.setSuspensionHeight(10);
  11. break;
  12. case COMFORT:
  13. vehicle.setPower(400);
  14. vehicle.setSuspensionHeight(20);
  15. break;
  16. default:
  17. vehicle.setPower(400);
  18. vehicle.setSuspensionHeight(20);
  19. break;
  20. //ECO라는 모드가 새롭게 추가되어야할때 , if~else가 계속하여 추가되는 형태가 됨
  21. //기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계하는 OCP에 위반
  22. }
  23. }
  24. }

solution

  1. public interface DrivingMode {
  2. int getPower();
  3. int getSuspensionHeight();
  4. }
  1. public class Comfort implements DrivingMode {
  2. private static final int POWER = 400;
  3. private static final int SUSPENSION_HEIGHT = 20;
  4. @Override
  5. public int getPower() {
  6. return POWER;
  7. }
  8. @Override
  9. public int getSuspensionHeight() {
  10. return SUSPENSION_HEIGHT;
  11. }
  12. }
  1. public class Sport implements DrivingMode {
  2. private static final int POWER = 500;
  3. private static final int SUSPENSION_HEIGHT = 10;
  4. @Override
  5. public int getPower() {
  6. return POWER;
  7. }
  8. @Override
  9. public int getSuspensionHeight() {
  10. return SUSPENSION_HEIGHT;
  11. }
  12. }
  1. public class Drive {
  2. private Vehicle vehicle;
  3. public Drive(final Vehicle vehicle) {
  4. this.vehicle = vehicle;
  5. }
  6. public void changeDrivingMode(final DrivingMode drivingMode){
  7. vehicle.setPower(drivingMode.getPower());
  8. vehicle.setSuspensionHeight(drivingMode.getSuspensionHeight());
  9. }
  10. }

#
L(리스코프 치환 원칙)
부모 클래스와 자식 클래스 사이의 행위가 일관성이 있어야 합니다.
즉,부모 클래스의 인스턴스 대신에 자식 클래스의 인스턴스로 대체해도 프로그램의 의미는 변화되지 않습니다.

  1. Vehicle vehicle =new Car();
  2. vehicle.changeGear(Gear.D);
  3. vehicle.changeGear(Gear.R);
  4. //자동차는 직진중에 후진할 수없다.
  1. Vehicle vehicle =new Plane();
  2. vehicle.changeGear(Gear.D);
  3. vehicle.changeGear(Gear.R);
  4. //비행기는는 직진중에 후진할 수 있다.
  1. Vehicle vehicle =new Vehicle();
  2. vehicle.changeGear(Gear.D);
  3. vehicle.changeGear(Gear.R);
  4. //비행기와 자동차의 상위클래스 탈것 클래스로 변경해도 똑같이 동작해야한다

#
I(인터페이스 분리 원칙)
하나의 일반적인 인터페이스보다는, 여러 개의 구체적인 인터페이스가 낫다
한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다는 원리입니다.

violation

  1. public interface Switches {
  2. void startEngine();
  3. void shutDownEngine();
  4. void turnRadioOn();
  5. void turnRadioOff();
  6. void turnCameraOn();
  7. void turnCameraOff();
  8. }
  1. public class Car extends Vehicle {
  2. //Vehicle은 Switches를 구현하고있습니다.
  3. private boolean radioOn;
  4. public boolean isRadioOn() {
  5. return radioOn;
  6. }
  7. @Override
  8. public void turnRadioOn() {
  9. radioOn = true;
  10. }
  11. @Override
  12. public void turnRadioOff() {
  13. radioOn = false;
  14. }
  15. @Override
  16. public void turnCameraOn() {
  17. // 안쓰는 함수를 구현하게됨,ISP위배
  18. }
  19. @Override
  20. public void turnCameraOff() {
  21. // 안쓰는 함수를 구현하게됨,ISP위배
  22. }
  23. }

#
I(의존관계 역전 원칙)
“추상화에 의존해야지, 구체화에 의존하면 안된다. 의존성 주입은 이 원칙을 따르는 방법 중 하나입니다.
위 레벨의 레이어가 하위 레벨의 레이어를 바로 의존하게 하는 것이 아니라 이 둘 사이에 존재하는 추상레벨을 통해 의존해야 한다.
이를 통해서 상위레벨의 모듈은 하위레벨의 모듈로의 의존성에서 벗어나 그 자체로 재사용 되고 확장성도 보장 받을 수 있습니다.

violaion

  1. public class RacingCar {
  2. private final int maxFuel;
  3. private int remainingFuel;
  4. private int power;
  5. public RacingCar(final int maxFuel) {
  6. this.maxFuel = maxFuel;
  7. remainingFuel = maxFuel;
  8. }
  9. public void accelerate(){
  10. power++;
  11. remainingFuel--;
  12. }
  13. }
  1. public class Pilot {
  2. private RacingCar car;
  3. public Pilot(){
  4. this.car = new RacingCar(100);
  5. }
  6. public void increaseSpeed(){
  7. car.accelerate();
  8. }
  9. }

solution

  1. public interface Vehicle {
  2. void accelerate();
  3. }
  1. public class RacingCar implements Vehicle{
  2. private final int maxFuel;
  3. private int remainingFuel;
  4. private int power;
  5. public RacingCar(final int maxFuel) {
  6. this.maxFuel = maxFuel;
  7. remainingFuel = maxFuel;
  8. }
  9. @Override
  10. public void accelerate() {
  11. power++;
  12. remainingFuel--;
  13. }
  14. }
  1. public class Pilot {
  2. private Vehicle vehicle;
  3. public Pilot(final Vehicle vehicle){
  4. this.vehicle = vehicle;
  5. }
  6. public void increaseSpeed(){
  7. vehicle.accelerate();
  8. }
  9. }