OOP 5대 원칙 SOLID

노을·2022년 3월 8일
0

java

목록 보기
5/9
post-thumbnail
post-custom-banner

⭐ SRP(Single Responsibility Principle): 단일 책임 원칙

어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.

  • 덧셈 로직을 바꾸고 싶다 → sum 클래스를 고친다 (O)
  • 덧셈과 뺄셈 로직을 바꾸고 싶다 → 계산기 로직을 바꾼다 (X)
public class Calculator {
    
    public int sum(int x,int y){ 
        return x + y; 
    }
    
    public int sub(int x,int y){
        return x - y; 
    }
    
    public int mul(int x,int y){ 
        return x * y;
    }
    
    public int div(int x,int y){ 
        return x / y; 
    }
}
public interface Calculator1 {
    public int calculate();
}

public class Sum implements Calculator1{
    @Override
    public int calculate(int x, int y) {
        return x + y ;
    }
}

public class Sub implements Calculator1{
    @Override
    public int calculate(int x, int y) {
        return x - y ;
    }
}

public class Mul implements Calculator1{
    @Override
    public int calculate(int x, int y) {
        return x * y ;
    }
}

public class Div implements Calculator1{
    @Override
    public int calculate(int x, int y) {
        return x / y ;
    }
}

그리고 작은 클래스 여러개를 만들어서 한 곳에 몰아 넣기보다는 이름과 기능에 따라 명확한 패키지에 나눠 넣어야 한다.


⭐ OCP(Open Closed Priciple): 개방 폐쇄 원칙

확장에는 열려있고 수정에는 닫혀있다.

기능을 추가할 때 코드 수정을 하는 것이 아니라 객체를 바꿔치기 한다.

수정 시 수정할 부분만 보여 줌으로써 주변의 변화를 막는다.

public class Sql {
    public Sql(String table, Column[] columns) {...}
    public String create()
    public String insert(Object[] fields)
    public String selectAll()
    public String findByKey(String keyColumn, String keyValue)
    public String select(Column column, String pattern)
    public String select(Criteria criteria)
    public String preparedInsert()
    private String columnList(Column[] columns)
    private String valuesList(Object[] fields, final Column[] columns) 
	private String selectWithCriteria(String criteria)
    private String placeholderList(Column[] columns)
	private String placeholderList(Column[] columns)
}

나중에 Update 메서드를 추가할 예정이다. 하지만 추가하려면 Sql 클래스 코드를 손대야 한다.

클래스에 손대면 다른 코드를 망가뜨릴 위험에 빠진다.

abstract public class Sql {
	public Sql(String table, Column[] columns) 
	abstract public String generate();
}
public class CreateSql extends Sql {
	public CreateSql(String table, Column[] columns) 
	@Override public String generate()
}

public class SelectSql extends Sql {
	public SelectSql(String table, Column[] columns) 
	@Override public String generate()
}

public class InsertSql extends Sql {
	public InsertSql(String table, Column[] columns, Object[] fields) 
	@Override public String generate()
	private String valuesList(Object[] fields, final Column[] columns)
}

public class SelectWithCriteriaSql extends Sql { 
	public SelectWithCriteriaSql(
	String table, Column[] columns, Criteria criteria) 
	@Override public String generate()
}

public class SelectWithMatchSql extends Sql { 
	public SelectWithMatchSql(String table, Column[] columns, Column column, String pattern) 
	@Override public String generate()
}

public class FindByKeySql extends Sql public FindByKeySql(
	String table, Column[] columns, String keyColumn, String keyValue) 
	@Override public String generate()
}

public class PreparedInsertSql extends Sql {
	public PreparedInsertSql(String table, Column[] columns) 
	@Override public String generate() {
	private String placeholderList(Column[] columns)
}

public class Where {
	public Where(String criteria) public String generate()
	public String generate() {
}

public class ColumnList {
	public ColumnList(Column[] columns) public String generate()
	public String generate() {
}

Update문을 추가할 때 기존 클래스를 변경할 필요가 없다.


⭐ LSP(Listov Substitution Priciple): 리스코프 치환 원칙

서브 타입은 언제나 자신의 기반 타입으로 교체할 수 있어야 한다.

하위 분류는 상위 분류의 한 종류다.

구현 분류는 인터페이스할 수 있어야 한다.

  • 사각형은 도형이 될 수 있지만 도형은 사각형이 될 수 없다.
    public abstract class Rectangle{...}
    public class Square extends Rectangle{...}
    
    //실행코드
    Rectangle rectangle = new Square();



⭐ ISP(Interface Segregation Principle): 인터페이스 분리 원칙

클라이언트는 자신이 사용하지 않는 메소드에 의존 관계를 맺으면 안 된다.

클라이언트가 의존하는 인터페이스에 사용하지 않는 메서드가 없도록 인터페이스를 각 역할에 분리 해야 한다.

공통되는 부분의 새로운 인터페이스로 분리한다 → 불필요한 코드를 줄일 수 있다.


⭐ DIP(Dependency Inversion Principle): 의존 역전 원칙

고차원 모듈은 저차원 모듈에 의존하면 안 된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다.

추상화된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다. 자주 변경되는 구체(Concrete) 클래스에 의존하지 마라

다시 말해서, 구현체 말고 인터페이스에 의존하여 내용을 변경하고 싶을 때는 구체 클래스를 바꾸어 기능을 수정한다. 이렇게 하면 코드 수정을 최소화 할 수 있다.


public class Car{
		Tire tire = new PlainTire(); //이부분에서 PlainTire 객체 타입을 Tire로 바꿨다.
		tire.roll();
}

public interface Tire{
    public boolean roll();
}
public class SnowTire implements Tire{
		@Override
		public boolean roll(){...}
}

public class PlainTire implements Tire{
		@Override
		public boolean roll(){...}
}

public class WideTire implements Tire{
    @Override
    public boolean roll(){...}
}

Car 클래스에서 Tire tire = new PlainTire(); 를 보면 PlainTire 객체를 Tire 클래스 타입으로 바꾸어 구현체가 아닌 인터페이스에 의존하게 만들었다.

이런식으로 추상화에 의존하면 객체를 교체하기 쉽다. 만약 WideTire 클래스의 roll 메서드를 작동하게 하고 싶으면 구현코드의 수정없이 Tire tire = new WideTire(); 로 객체를 갈아끼우면 된다.

따라서 수정하기 편해지고 오류를 방지할 수 있다.

post-custom-banner

0개의 댓글