확장에는 열려있고 변화에는 닫혀있다는 뜻. 다시 말하면, 변경사항에 대해 기존 코드는 변경하지 않고(Closed) 확장(extends)으로 해결하는 것을 의미한다.
직접적으로 두 클래스 간에 직접적으로 의존하게 되면 기존 코드에 변경이 생길 수 밖에 없다. 구현체에 대한 의존을 줄이고 인터페이스에 의존하여 해당 인터페이스를 구현한 클래스를 통해 기능을 추가 하는 방식이 OCP이다.
picture 1. OCP적용
picture 2. OCP 적용2
class Person {
String type;
Person(String type) {
this.type = type;
}
}
class EatFood {
void eat(Person person) {
if (person.type.equals("student")) {
System.out.println("학생이 먹습니다.");
} else if (person.type.equals("professor")) {
System.out.println("교수가 먹습니다.");
}
}
}
public class Main {
public static void main(String[] args) {
EatFood eatFood = new EatFood();
Person student = new Person("student");
Person professor = new Person("professor");
eatFood.eat(student);
eatFood.eat(professor);
}
}
class Person {
String type;
Person(String type) {
this.type = type;
}
}
class EatFood {
void eat(Person person) {
if (person.type.equals("student")) {
System.out.println("학생이 먹습니다.");
} else if (person.type.equals("professor")) {
System.out.println("교수가 먹습니다.");
} else if (person.type.equals("worker")) {
System.out.println("워커가 먹습니다.");
}
}
}
public class Main {
public static void main(String[] args) {
EatFood eatFood = new EatFood();
Person student = new Person("student");
Person professor = new Person("professor");
Person worker = new Person("worker");
eatFood.eat(student);
eatFood.eat(professor);
eatFood.eat(worker);
}
}
student
와 professor
만 있는 코드에서, 새로운 worker
를 추가하게 된다면 EatFood
class를 변경해야한다. 이는 기존코드를 수정하여 OCP에 위반된다. 이 코드를 확장으로 해결한다면 다음과 같다.
abstract interface Person {
abstract void eat();
}
class Student implements Person {
@Override
public void eat() {
System.out.println("학생이 먹습니다.");
}
}
class Professor implements Person {
@Override
public void eat() {
System.out.println("교수가 먹습니다.");
}
}
class Worker implements Person {
@Override
public void eat() {
System.out.println("워커가 먹습니다.");
}
}
class EatFood {
void eat(Person person) {
person.eat();
}
}
public class Main {
public static void main(String[] args) {
EatFood eatFood = new EatFood();
Person student = new Student();
Person professor = new Professor();
Person worker = new Worker();
eatFood.eat(student);
eatFood.eat(professor);
eatFood.eat(worker);
}
}
새로운 기능 개발로 추상 클래스 Person
를 구현한 새로운 클래스 Worker
를 추가하였다.(extends - open), 기존 코드인 Professor
와 Student
는 변경되지 않는다.(modification-close)
이를 통해, 변경사항에 유연한 코드를 작성할 수 있게 된다.
참고
SOLID Design Principles Explained: The Open/Closed Principle with Code Examples