햄버거,코크,프렌치프라이와 햄버거 세트
새로운 형태의 클래스를 만들고자 할 때 기존의 만들어져 클래스를 이용하는 것이 아주
효율적 일때가 있습니다.
처음부터 새로 만드는 것보다 기존에 만들어진 클래스를 이용할 수 있다면 비용을
줄일수 있고 실수를 하지 않을 수 있기 때문입니다.
롯데리아에서 팔고 잇는 빅립버거, 코크, 프렌치프라이를 자바로 만들어 봤습니다.
빅립버거는 burger 패키지에, 코크는 beverage 패키지에,프렌치 프라이는 snack
패키지에 속하도록 했습니다. 적절한 이름이지요. 그쵸?
package burger;
/**
* 롯데리아에서 파는 맛있는 BigRib버거
*/
public class BigRibBurger {
private int price;
private String description;
public BigRibBurger(int price,String description) {
this.price = price;
this.description = description;
}
public BigRibBurger(int price) {
this(price,"best selling burger in 2002");
}
public BigRibBurger(String description) {
this(2500,description);
}
public BigRibBurger() {
this(2500,"best selling burger in 2002");
}
public int getPrice() {
return price;
}
public String getDescription() {
return description;
}
}
예제 3 - 1 BigRibBurger.java
package beverage; // beverage 패키지
/**
* 롯데리아에서 파는 맛있는 코카코라
*/
public class Coke {
private int price;
private String description;
public Coke(int price, String description) {
this.price = price;
this.description = description;
}
public Coke(int price) {
this(price,"best selling beverage in 2002");
}
public Coke(String description) {
this(1100,description);
}
public Coke() {
this(1100,"best selling beverage in 2002");
}
public int getPrice() {
return price;
}
public String getDescription() {
return description;
}
}
예제 3 - 2 Coke.java
package snack; // snack 패키지
/**
* 롯데리아에서 파는 맛있는 프렌치프라이
*/
public class FrenchFried {
private int price;
private String description;
public FrenchFried(int price, String description) {
this.price = price;
this.description = description;
}
public FrenchFried(int price) {
this(price,"best selling snack in 2002");
}
public FrenchFried(String description) {
this(800,description);
}
public FrenchFried() {
this(800,"best selling snack in 2002");
}
public int getPrice() {
return price;
}
public String getDescription() {
return description;
}
}
예제 3 - 3 FrenchFried.java
빅립버거, 코크, 프렌치프라이에 대한 개념을 구체화해서 객체로 잘 사용하고 있는데,
마침 회사에서 빅립버거세트 라는 것을 상품으로 내놓았습니다.
그런데 알고보니 빅립버거세트라는 것은 없다가 생긴개념이 아니라 빅립버거와 코크,
프렌치프라이를 한꺼번에 판매하는 개념이라고 합니다.
이런 경우 처음부터 빅립버거세트에 대한 개념을 새로 만들어 클래스로 정의할 수
있겠지만 곰곰히 생각해보면 빅립버거세트는 다름아닌, 빅립버거와 코크,프렌치프라이를
합친 것에 다름 아닙니다.
빅립버거세트 클래스를 설계할 때 기존에 존재하는 다른 객체들,빅립버거,코크,프렌치]
프라이 등을 다시 사용한다면 처음부터 새롭게 만들지 않고도 효율적으로 설계를 할 수
있습니다. 빅립버거세트는 빅립버거,코크,프렌치프라이 객체로 구성되어 있기 때문입니다.
빅립버거,코크,프렌치프라이등의 객체의 멤버변수등이 가격과 개요등, int형, String형
으로 구성되어있다고해서 빅립버거세트의 멤버변수를 가격,개요 즉, int형,String형으로
구성할 필요는 없습니다.
좀더 간명하고 넓게 생각해 보면 빅립버거세트는 한 개의 빅립버거,한 개의 코크,한 개의
프렌치프라이로 구성되어 있다고 생각하는 것입니다.
물론 빅립버거세트 또한 가격이 있고,개요가 있겠지만 그렇게 생각하지 않고
빅립버거세트는 빅립버거,코크,프렌치프라이로 구성되어 있다고 생각하고 버거,코크,프렌치프라이등 기존에 존재하는 객체를 멤버변수로 이용해서 새로운 객체를 구현하는 방법을
콤포지션 (Composition) 이라고 합니다.
package burger; // burger 패키지
import beverage.*; // beverage 패키지를 이용함
import snack.*; // snack 패키지를 이용함
/**
* 롯데리아에서 파는 맛있는 빅립버거세트
*/
public class BigRibBurgerSet {
/**
* 빅립버거세트의 빅립햄버거
*/
private BigRibBurger burger;
/**
* 빅립버거세트의 코카콜라
*/
private Coke coke;
/**
* 빅립버거세트의 프렌치프라이
*/
private FrenchFried fried;
/**
* 빅립버거세트가 빅립버거,코크,프렌치프라이로 구성됩니다.
*/
public BigRibBurgerSet(BigRibBurger burger,Coke coke,FrenchFried fried) {
this.burger = burger;
this.coke = coke;
this.fried = fried;
}
/**
* 빅립버거세트의 가격은 빅립버거의 가격, 코크의 가격, 프렌치프라이의 가격을
* 합산한 것과 같습니다.
*/
public int getPrice() {
return burger.getPrice() + coke.getPrice() + fried.getPrice();
}
/**
* 빅립버거세트의 개요는 빅립버거세트를 구성하는 빅립버거,코크,프렌치프라이의
* 개요을 모두 나열하는 것으로 정하면 간명하겠네요.
* 이게 싫다면 새로운 개요를 정해도 되겠습니다.
*/
public String getDescription() {
StringBuffer sb = new StringBuffer();
sb.append(burger.getDescription()).append(",");
sb.append(coke.getDescription()).append(",");
sb.append(fried.getDescription()).append("\n");
return sb.toString();
}
public static void main(String[] args) {
BigRibBurgerSet bs =
new BigRibBurgerSet(new BigRibBurger(),new Coke(),new FrenchFried());
System.out.println("BigRibBurgerSet's Price = " + bs.getPrice());
System.out.println("BigRibBurgerSet = " + bs.getDescription());
}
}
예제 3 - 4 BigRibBurgerSet.java
예제 3 - 4 BigRibBurgerSet 클래스를 살펴보면 처음부터 새롭게 설계하지 않고, 기존의
객체들을 합해서 만들어 냈습니다.
그림 3 - 1 [ compile run (BigRibBurgerSet.java) ]
이렇게 콤포지션을 사용하여 새로운 객체를 만들어 내는 것을 실제로 아주 빈번하고
또한 좋은 설계방법이라고 생각합니다. 이런 콤포지션을 이용하는 방법은 객체의 형태를
이용한다기 보다는 기존의 객체가 갖고 있는 기능을 충분히 활용하는 것이고, 개념적으로도
상당히 쉽게 접근할 수 있습니다.
만약 BigRibBurgerSet를 콤포지션을 이용하지 않고, 그냥 만들었다면 아마 예제 3 - 5와
같이 만들수 있을 것입니다.
package burger;
/**
* 롯데리아에서 파는 맛있는 빅립버거세트
*/
public class BigRibBurgerSet {
private int price;
private String description;
public BigRibBurgerSet(int price,String description) {
this.price = price;
this.description = description;
}
public BigRibBurgerSet(int price) {
this(price,"best selling burger set in 2002");
}
public BigRibBurgerSet(String description) {
this(2500,description);
}
public BigRibBurgerSet() {
this(2500,"best selling burger set in 2002");
}
public int getPrice() {
return price;
}
public String getDescription() {
return description;
}
}
예제 3 - 5
빅립햄버거 세트역시 빅립햄버거와 마찮가지로 가격이 있고, 개요가 있는 정보이므로
예제 3 - 5와 같이 구성해도 별 무리는 없겠습니다만, 추후에 콜라가격이 변동을 하거나,
빅립버거의 가격이 변동을 하거나 어떤 변경이 있을 때 BigRibBurgerSet의 클래스의 경우
반드시 변동분을 일일이 반영해주어야 합니다. 왜냐하면 BigRibBurgerSet 클래스는
빅립햄버거,코크,프렌치 프라이드로 이루어져 있는 현실의 빅립햄버거세트에 대한 개념화를
빅립햄버거,코크,프렌치프라이드로 구성되어 있다고 생각하지 않고, 단지 가격과 개요만
있는 것으로 개념화해서 클래스를 설계 했기 때문입니다.
추후에 빅립햄버거의 가격이 500원 내리면 빅립햄버거 세트의 가격도 500원 자동으로
내려야하지만 예제 3 - 5의 클래스를 사용한 프로그램에서는 매우 곤란합니다.
예제 3 - 4의 클래스를 사용한 프로그램은 별 문제가 없을 겁니다. 왜냐하면
500원 할인된 빅립햄버거 객체를 생성자에서 받으면 되니까요.
예제 3 - 5 의 클래스 설계보다는 여러모로 보아 예제 3 - 4의 콤포지션을 이용하는
편이 훨씬 유연하고 , 프로그램의 사고가 우리가 살아가는 현실과 닮았습니다.
빅립버거세트의 가격은 빅립버거와 코크,프렌치프라이의 가격의 합과 같고,
빅립버거세트의 개요는 빅립버거와, 코크,프렌치프라이의 개요를 모두 합한것과
같으니까요.
예제 3 - 4와 같이 자바에서는 기존에 만들어진 객체를 활용하는 멋진 방법이 있는데
대표적인 것이 콤포지션이라는 방법이고, 그 다음으로 많이 쓰이는 것이 상속이라는
것입니다.
'자바 Basic > 클래스의 재사용' 카테고리의 다른 글
자바공부-2.상속 (Inheritance) (0) | 2007.11.30 |
---|