객체지향 설계 안에 존재하는 세가지 상호 연관된 관점
1. 개념 관점 ( Conceptual Perpective )
- 개념과 개념들 사이의 관계
2. 명세 관점 ( Specification Perspective ) 인터페이스
- 객체들의 책임, 객체가 협력을 위해 무엇을 할 수 있는가
3. 구현 관점 ( Implementation perspective )
- 객체의 책임을 어떻게 수행 할 것인가.
클래스는 세 가지 관점을 모두 수용할 수 있도록 개념, 인터페이스, 구현을 함께 드러내야 한다.
동시에 코드 안에서 세가지 관점을 쉽게 식별할 수 있도록 분리해야한다.
커피전문점 예제의 목표
1. 도메인 모델에서 시작해서 최종 코드까지의 구현과정을 설명
2. 구현 클래스를 개념,명세,구현 관점에서 바라보는 것이 무엇을 의미하는지 설명
커피 전문점 도메인
Menu : 아메리카노, 카푸치노, 마끼아또, 에스프레소 (4개)
도메인
- 손님 객체
- 메뉴항목 객체
- 메뉴판 객체
- 바리스타 객체
- 커피 객체
객체들간의 관계
- 손님은 메뉴판을 알아야 함
- 손님은 바리스타에게 메뉴주문
- 바리스타는 커피를 제조
포함관계 또는 합성관계
메뉴항목 객체는 메뉴판 객체에 포함되어 있음
연관관계
손님은 메뉴판을 알아야하지만
메뉴판은 손님의 일부가 아니므로 포함관계는 아니다.
그냥 서로 알고 있어야할 경우가 연관관계
커피전문점의 도메인을 단순화시킨것
연관관계, 포함관계가 중요한것은 아니다.
실제로는 각 객체들 사이에 관계가 존재한다는 사실을 이해하는 것이 중요하다.
다음단계는 협력을 설계하는 것.
즉, 적절한 객체에게 적절한 책임을 할당
설계하고 구현하기
협력찾기
메시지를 먼저 선택하고, 메시지를 수신하기에 적절한 객체를 선택해야 한다.
1. 커피를 주문하라
- 어떤 객체가 커피를 주문할 책임이 있는가 = 손님
- 손님은 메뉴항목을 모른다
2. 메뉴 항목을 찾아라
- 어떤 객체가 메뉴 항목을 반환할 수 있는가 = 메뉴판
- 메뉴항목을 얻었으니 커피를 제조해달라고 요청할 수 있다
3. 커피를 제조하라
- 바리스타는 커피제조법을 모두 알고 있다(자율적인 객체 : 어떻게 만들든 상관없지)
인터페이스 정리하기
객체가 수신한 메시지가 객체의 인터페이스를 결정한다.
객체의 인터페이스 안에 메시지에 해당하는 오퍼레이션(외부에서 접근 가능한)이 존재한다.
- 손님객체 : 제품을 주문하라
- 메뉴판객체 : 메뉴 항목을 찾아라
- 바리스타 객체 : 커피를 제조하라
- 커피 객체 : 생성하라
Class Customer { public void order(String menuName){} } Class MenuItem{ } Class Menu{ public MenuItem choose(String name) {} } Class Barista{ public Coffee makeCoffee(MenuItem menuItem) {} } Class Coffee{ public Coffee(MenuItem menuItem) {} } |
구현하기
/* * 1. Menu에게 menuName에 해당하는 MenuItem을 요청해야 함 * 2. 이를 받아 Barista에게 커피만들라고 전달해야함 * 3. 즉 Menu객체와 Barista 객체에 대한 참조를 알아야하므로 인자로 전달받는 방법을 선택 */ class Customer { // Menu, Barista 객체를 인자로 받음 public void order(String menuName, Menu menu, Barista barista) { // Menu에게 menuName에 해당하는 MenuItem을 요청 MenuItem menuItem = menu.choose(menuName); // 전달받은 MenuItem으로 Baraista에게 커피만들라고 요청 Coffee coffee = barista.makeCoffee(menuItem); // .... } } /* * 1. menuName 에 해당하는 MenuItem을 찾아야 함 * 2. 이를 위해 내부적으로 MenuItem을 관리 */ class Menu { private List<MenuItem> items; public Menu(List<MenuItem> items) { this.items = items; } // 요청온 name으로 MenuItem에서 커피이름과 가격을 조회 public MenuItem choose(String name) { for (MenuItem each : items) { if (each.getName().equals(name)) { return each; } } return null; } } /* * 커피를 만들어서 Coffee 리턴 */ class Barista { public Coffee makeCoffee(MenuItem menuItem) { Coffee coffee = new Coffee(menuItem); return coffee; } } /* * 1. 자기 자신을 생성하기 위한 생성자를 제공 * 2. Coffe는 커피이름과 가격을 가지고 생성자 안에서 MenuItem에 요청을 보내 * 커피 이름과 가격을 얻고 속성에 저장 */ class Coffee { private String name; private int price; public Coffee(MenuItem menuItem) { this.name = menuItem.getName(); this.price = menuItem.getCost(); } } /* * 메뉴 item */ class MenuItem{ private String name; private int price; public MenuItem(String name, int price) { this.name = name; this.price = price; } public int getCost() { return this.price; } public String getName() { return this.name; } } |
'책 > 객체지향의 사실과오해' 카테고리의 다른 글
객체지향의 사실과 오해) 부록. 추상화 기법 (0) | 2020.02.06 |
---|---|
객체지향의 사실과 오해) 06 / 객체 지도 (0) | 2020.01.25 |
객체지향의 사실과 오해) 05 / 책임과 메시지 (0) | 2020.01.24 |
객체지향의 사실과 오해) 04 / 역할, 책임, 협력 (0) | 2020.01.16 |
객체지향의 사실과 오해) 03 / 타입과 추상화 (0) | 2020.01.08 |