2. 개요
2
software entities(classes, modules, functions, etc) should be open for
extension, but closed for modification.
소프트웨어 객체(클래스, 모듈, 함수 등)는 확장은 가능하지만 변경은 불가해야 한다.
단일 객체의 변경이 여러 의존적인 모듈의 변경을 초래한다면
* fragile : 깨지기 쉬움
* rigid : 변경이 어려움
* unpredictable : 예측 불가
* unreusable : 재사용 불가
“절대 변경되지 않는” 모듈의 설계를 가정할것.
요구사항이 변경될 경우
* 기존 코드 수정 X, 해당 요구사항을 코드 추가로 해결
3. 기본 속성
3
1. 확장에는 열려 있음
모듈의 동작이 확장 가능함 -> 요구사항 변경 또는 새로운 어플리케이션에 따라 (새로
운/다른) 동작을 구현 가능
2. 변경에는 닫혀 있음
이런 모듈의 소스코드는 변경이 불가능
4. 예제 : Non-OCP
public class ShapeNonOCP {
public static void main(String[] args) {
Square square = new Square(10, 5);
Circle circle = new Circle(7);
nonOcp.drawAllShapes(new Object[] { square, circle });
}
private void drawAllShapes(Object[] objects) {
for (Object obj : objects) {
if (obj instanceof Square) {
drawSquare((Square) obj);
} else if (obj instanceof Circle) {
drawCircle((Circle) obj);
}
}
}
private void drawSquare(Square square) {
System.out.println("square area : " + (square.width * square.height));
}
private void drawCircle(Circle circle) {
System.out.println("circle area : “ + (Math.pow(circle.radius, 2) * Math.PI));
}
}
public class Square {
int width;
int height;
public Square(int width, int height) {
this.width = width;
this.height = height;
}
}
public class Circle {
int radius;
public Circle(int radius) {
this.radius = radius;
}
}
4
5. 예제 : OCP
package net.daum.test.ocp;
public class ShapeOCP {
public static void main(String[] args) {
Shape square = new Square(10, 5);
Shape circle = new Circle(7);
ocp.drawAllShapes(new Shape[] { square, circle });
}
private void drawAllShapes(Shape[] shapes) {
for (Shape shape : shapes) {
shape.draw();
}
}
}
public interface Shape {
public void draw();
}
public class Square implements Shape {
int width;
int height;
public Square(int width, int height) {
this.width = width;
this.height = height;
}
public void draw() {
System.out.println("square area : " +
(this.width * this.height));
}
}
public class Circle implements Shape {
int radius;
public Circle(int radius) {
this.radius = radius;
}
public void draw() {
System.out.println("circle area : "
+ (Math.pow(this.radius, 2) * Math.PI));
}
}
5
6. 선택 전략
실제 상황에선 100% close할수 없을 경우가 존재함.
예) drawAllShapes함수에서 square를 circle보다 먼저 처리해야 할 경우
-> 설계시 변경의 종류를 고려하여 close의 여부를 결정할것.
방법 1) 추상화
sort객체를 생성하여 사용. shape객체의 변경시 sort객체도 변경
방법 2) data기준 처리
order table사용. table에 의해 ordering
6
7. 관례
모든 멤버변수를 private으로 선언
•멤버변수의 변경이 다른 객체에게 영향을 주지 않음
•멤버변수의 접근권한이 상속되지 않음 -> 접근/수정권한의 귀속
•멤버변수로의 접근 제어
Global변수 사용금지
RTTI(run time type identification) 사용 금지
7
8. OCP의 변화
Meyer의 OCP 정의
•1988년 Bertrand Meyer의 저서 Object Oriented Software Construction 정의
•한번 구현된 객체는 오류수정을 위해서만 변경 가능
•새 기능/변경된 기능은 별도의 상속된 객체를 이용
•구현의 상속
•부모 객체의 인터페이스(spec)와 자식 객체의 인터페이스는 다를 수 있음
•부모 객체의 코드 재사용 목적
다형성을 가짂 OCP 정의
•1990년대에 재 정의된 OCP
•구현이 변경 가능하며 다중의 구현이 생성되어 다형성을 통해 상호 참조 가능
•인터페이스(spec)의 상속
•부모 객체의 인터페이스(spec)와 자식 객체의 인터페이스가 호홖 가능해야 함
•실제 구현은 다를 수 있음
8
9. OCP 주의점
공통부분/변경부분의 적절한 비율 조절
•공통부분(private field/private method)가 너무 많으면 구조 및 설계가 비 직관적
•공통부분이 너무 적으면 재사용성이 떨어짐
인터페이스 정의시 향후 사용패턴에 대한 예지력(?)을 발휘할것
•한번 정해짂 인터페이스의 변경에는 많은 비용이 소모
•예) java의 deprecated API, 표준 java.*패키지와 javax.*패키지
설계시 적절한 추상화의 레벨 선정
•Grady Booch : 추상화란 다른 모든 종류의 객체로부터 식별될 수 있는 객체의 본질
적인 특징
•IInputStream.doWork() -> X
•IInputStream.read() -> O
•IInputStream.readFromHttp() -> X
9