SOLID - 개방-폐쇄 원칙(OCP)

Kim, Beomgoo·2022년 8월 31일
0

OOP

목록 보기
2/2

정의

소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.

소프트웨어 개발에 이용된 모듈들 중 하나를 수정할 때, 이 모듈과 관련된 코드를 연쇄적으로 고쳐야 한다면 유지보수성이 떨어진다. OCP는 기능을 추가하거나 변경해야 할 때, 기존 코드를 변경하지 않고 새로운 코드를 추가함으로써 기능의 추가나 변경이 가능하게 하여, 코드 변경에 따른 영향력을 낮추는 것을 목적으로 한다.

OCP를 위배하는 코드

public class Human {
	
	private String nation;	

	public Human(String nation) {
		this.nation = nation;
	}

	public void salute() {
		if (nation.equals("Korea")) {
			System.out.println("안녕하세요");
		} else if (nation.equals("America")) {
			System.out.println("Hello");
		}
	}
}

public class ClientClass {
	
	public static void main(String[] args) {
		Human korean = new Human("Korea");
		Human american = new Human("America");

		korean.salute();     // 안녕하세요
		american.salute();   // Hello
	}
}

위와 같이 Human 클래스가 있다. 이 상황에서 main 메소드에서 koreanamerican 말고 새로운 Human 객체인 japanese를 만든다면 어떻게 될까?

public class ClientClass {
	
	public static void main(String[] args) {
		Human korean = new Human("Korea");
		Human american = new Human("America");

		korean.salute();     // 안녕하세요
		american.salute();   // Hello

		Human japanese = new Human("Japan");
		japanese.salute();   // 제대로 작동하지 않음!
	}
}

salute() 메소드에서 Japan에 대한 처리를 아직 하지 않아서 제대로 작동하지 않는다. 제대로 작동하게 하려면 Human 클래스를 수정해야 한다. 이때 ‘변경에 닫혀 있어야 한다'는 OCP를 위반하게 된다.

추상화를 이용하자!

객체지향 프로그래밍에서는, 가능한 동작의 묶음을 표현하는 추상화(abstraction)가 가능하다. 추상 클래스를 상속받은 파생 클래스는 고정된 추상화에 의존하기 때문에 수정에 닫혀 있을 수 있고, 추상 클래스의 새로운 파생 클래스를 만들어 확장에 대해 열려 있을 수 있다. 이를 통해 추상화는 OCP의 핵심 요소임을 알 수 있다.

OCP를 준수하도록 리팩토링한 코드

public abstract class Human {
	
	private String nation;

	public Human(String nation) {
		this.nation = nation;
	}

	public abstract void salute();
}
public class Korean extends Human {
	
	public Korean(String nation) {
		super(nation);
	}

	@Override
	public void salute() {
		System.out.println("안녕하세요");
	}
}

public class American extends Human {
	
	public American(String nation) {
		super(nation);
	}

	@Override
	public void salute() {
		System.out.println("Hello");
	}
}

Human 클래스를 추상 클래스로 만들고, 이를 상속하여 Korean 클래스와 American 클래스로 만들었다. 이를 이용하는 main 메소드는 이전과 동일하다.

public class ClientClass {
	
	public static void main(String[] args) {
		Human korean = new Human("Korea");
		Human american = new Human("America");

		korean.salute();     // 안녕하세요
		american.salute();   // Hello
	}
}

이때 Japanese를 추가하려면 아래와 같이 Human 추상 클래스를 다시 한번 상속하여 만들면 된다.

public class Japanese extends Human {
	
	public Japanese(String nation) {
		super(nation);
	}

	@Override
	public void salute() {
		System.out.println("Kon'nichiwa");
	}
}

public class ClientClass {
	
	public static void main(String[] args) {
		Human korean = new Human("Korea");
		Human american = new Human("America");

		korean.salute();     // 안녕하세요
		american.salute();   // Hello

		Human japanese = new Human("Japan");
		japanese.salute();   // Kon'nichiwa
	}
}

OCP가 주는 이점

  • 유연성, 재사용성, 유지보수성
profile
하나에 하나를 보탠다

0개의 댓글