디자인 패턴 - 객체지향 원리

JAVA 객체 지향 디자인 패턴 책을 정리.

추상화

어떤 영역에서 필요로 하는 속성이나 행동을 추출하는 작업을 의미.

교육학 용어 사전에서의 추상화 정의

추상화는 사물들의 공통된 특징, 즉 추상적 특징을 파악해 인식의 대상으로 삼는 행위이다. 추상화가 가능한 개체들은 개체가 소유한 특성의 이름으로 하나의 집합을 이룬다. 그러므로 추상화한다는 것은 여러 개체들을 집합으로 파악한다는 것과 같다. 추상적 특성은 집합을 구성하는 개체들을 ‘일반화’하는 것이므로 집합의 요소들에 보편적인 것이다.

캡슐화

항상 소프트웨어를 설계하거나 구현하는 중에 요구사항이 변경되는 일이 많아 소프트웨어 개발자들은 굉장히 힘들어 한다. 그렇다고 아무리 시간을 많이 들여 요구사항을 철저하게 분석해도 요구사항이 변경되는 경우는 거의 없다. 그러니 요구사항 변경을 당연하게 받아들이고 이에 대처하는 법을 터득해야 한다.

소프트웨어 공학에서 요구사항 변경에 대처하는 고전적인 설계 원리는 응집도(cohesion)와 결합도(coupling)가 있다.

  • 응집도: 클래스나 모듈 안의 요소들이 얼마나 밀접하게 관련되어 있는지를 나타냄.
  • 결합도: 어떤 기능을 실행하는 데 다른 클래스나 모듈들에 얼마나 의존적인지를 나타냄.

높은 응집도와 낮은 결합도를 유지하도록 설계해야 요구사항 변경할 때 유연하게 대처할 수 있다.

캡슐화는 낮은 결합도를 유지할 수 있도록 해주는 객체지향 설계 원리이다.

그 중에서도 정보 은닉(information hiding)을 통해 높은 응집도와 낮은 결합도를 갖도록 한다.

  • 정보 은닉: 알 필요 없는 정보를 외부에서 접근하지 못하도록 제한하는 것

일반화 관계

객체지향 프로그래밍 관점에서는 상속 관계라고 한다.

철학에서 일반화란,

여러 개체들이 가진 공통된 특성을 부각시켜 하나의 개념이나 법칙으로 성립시키는 과정

다음은 '사람'이 자동차를 사용하는 상황을 묘사한 것이다.

BMW, 소나타, 벤츠의 공통된 개념은 자동차일 것이다. 즉, 자동차는 BMW, 소나타, 벤츠가 가진 공통 개념을 일반화한 개념이며, BMW, 소나타, 벤츠는 자동차를 특수화(specialization)한 개념이다.

이렇게 일반화하면 각각의 자동차의 종류에 신경 쓰지 않고 자동차 전체를 다룰 수 있는 수단이 생긴다.

그리고 일반화 관계는 자식 클래스를 외부로부터 은닉하는 캡슐화의 일종이다. 위의 그림에서 '사람' 클래스 관점에서는 구체적인 자동차의 종류가 숨겨져 있다. 어떤 자동차의 종류이건 '운전한다'라는 건 똑같기 때문에 '사람'이 어떤 자동차인지에 따라 영향을 받지 않는다.

일반화 관계와 위임

기본적으로 일반화 관계는 'is a kind of' 관계가 성립되어야 한다.

Stack is a kind of ArrayList

예를 들어, ArrayList 클래스 대신에 Stack 클래스를 사용할 수 있는지를 평가하면 된다. 대부분의 프로그램에서 ArrayList 대신 Stack을 사용할 수 없으므로 일반화에 적합하지 않다.

이 관계가 성립하지 않을 때 상속을 사용하면 불필요한 속성이나 연산도 물려받게 된다.

어떤 클래스의 일부 기능만 재사용하고 싶다면 위임(delegation)을 사용하면 된다.

  • 위임: 자신이 직접 기능을 실행하지 않고 다른 클래스의 객체가 기능을 실행하도록 위임하는 것.

다형성

서로 다른 클래스의 객체가 같은 메시지를 받았을 때 각자의 방식으로 동작하는 능력.

피터 코드의 상속 규칙

피터 코드(Peter Code)는 상속의 오용을 막기 위해 상속의 사용을 엄격하게 제한하는 규칙들을 만들었다. 5가지 규칙이 있으며, 어느 하나라도 만족하지 않으면 상속을 사용해서는 안된다.

  • 자식 클래스와 부모 클래스 사이는 역할 수행관계가 아니어야 한다.
  • 한 클래스의 인스턴스는 다른 서브 클래스의 객체로 변환할 필요가 절대 없어야한다.
  • 자식 클래스가 부모 클래스의 책임을 무시하거나 재정의하지 않고 확장만 수행해야한다.
  • 자식 클래스가 단지 일부 기능을 재사용할 목적으로 유틸리티 역할을 수행하는 클래스를 상속하지 않아야한다.
  • 자식 클래스가 역할, 트랜잭션, 디바이스 등을 특수화해야한다.
김땡땡's blog

김땡땡's blog

김땡땡