Open 확장(extends나 implements)에 열려있다. 다른애가 수정이 되면 또 다른 implement클래스나 extends클래스를 만들어서 수정하고 건드리지 마라.

기존에도 추상클래스를 상속하고 있어야한다는 의미.

문제들의 대한 공통점을 인식해서 추상화했다는 의미

정의

확장에는 열려있고 변화에는 닫혀있다는 뜻. 다시 말하면, 변경사항에 대해 기존 코드는 변경하지 않고(Closed) 기능을 추가(Open)하는 것을 의미한다.

직접적으로 두 클래스 간에 직접적으로 의존하게 되면 기존 코드에 변경이 생길 수 밖에 없다. 구현체에 대한 의존을 줄이고 인터페이스에 의존하여, 인터페이스를 구현하는 새로운 클래스를 이용한 방식이 확장에 열려있게 하는 게 OCP이다.

예시

picture 1. OCP적용

picture 1. OCP적용

picture 2. OCP 적용2

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); 
    }
}

studentprofessor 만 있는 코드에서, 새로운 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);
    }
}