취약한 기반 클래스 문제
라고 부른다.클래스 폭발
또는 조합의 폭발
문제라고 부른다.상속보다 재사용을 사용했을 때 어떤 장점들이 있는지 예제 코드를 통해서 알아보자.
인터페이스에 대고 프로그래밍하기
부터 시작해보겠다.
Eatable
인터페이스와 이를 구현하는 FastFood
클래스를 만들어보자.public interface Eatable {
void buy();
void eat();
void clean();
}
public abstract class FastFood implements Eatable {
private String name;
public FastFood(String name) {
this.name = name;
}
public void printName() {
System.out.println(name);
}
@Override
public void buy() {
System.out.println("음식을 구매했습니다.");
}
@Override
public void eat() {
System.out.println("음식을 먹습니다.");
}
@Override
public void clean() {
System.out.println("쓰레기를 정리합니다.");
}
abstract public boolean isDoublePatty();
abstract public void drink();
abstract public void empty();
}
public class CheeseBurgerSprite extends FastFood {
public CheeseBurgerSprite(String name) {
super(name);
}
@Override
public boolean isDoublePatty() {
return false;
}
@Override
public void drink() {
System.out.println("사이다를 마십니다.");
}
@Override
public void empty() {
System.out.println("사이다를 다 마셨습니다.");
}
}
public class CheeseBurgerCola extends FastFood {
public CheeseBurgerCola(String name) {
super(name);
}
@Override
public boolean isDoublePatty() {
return false;
}
@Override
public void drink() {
System.out.println("콜라를 마십니다.");
}
@Override
public void empty() {
System.out.println("콜라를 다 마셨습니다.");
}
}
public class Application {
public static void main(String[] args) {
CheeseBurgerCola fastFood = new CheeseBurgerCola("치즈버거 + 콜라");
fastFood.printName();
System.out.println(fastFood.getSugar());
fastFood = new CheeseBurgerZeroCola("치즈버거 + 제로콜라");
fastFood.printName();
System.out.println(fastFood.getSugar());
fastFood = new CheeseBurgerSprite("치즈버거 + 사이다");
// 컴파일 에러 발생
fastFood.printName();
System.out.println(fastFood.getSugar());
}
}
조합은 어렵지 않다. 조합의 대상이 되는 객체들을 분리해서 인스턴스 변수로 참조하는 것이 전부이다. 아래 Burger와 Beverage처럼 말이다.
public class FastFood implements Eatable {
private Burger burger;
private Beverage beverage;
public FastFood(Burger burger, Beverage beverage) {
this.burger = burger;
this.beverage = beverage;
}
public void setBurger(Burger burger) {
this.burger = burger;
}
public void setBeverage(Beverage targetBeverage) {
this.beverage = targetBeverage;
}
public void printName() {
System.out.println(burger.getName() + "+" + beverage.getName());
}
@Override
public void buy() {
System.out.println("음식을 구매했습니다.");
}
@Override
public void eat() {
System.out.println("음식을 먹습니다.");
}
@Override
public void clean() {
System.out.println("쓰레기를 정리합니다.");
}
}
// Beverage.java
public abstract class Beverage {
private String name;
private int sugar;
public Beverage(String name, int sugar) {
this.name = name;
this.sugar = sugar;
}
public String getName() {
return name;
}
public int getSugar() {
return sugar;
}
abstract void drink();
abstract void empty();
}
// Burger.java
public abstract class Burger {
private String name;
public Burger(String name) {
this.name = name;
}
public String getName() {
return name;
}
abstract boolean isDoublePatty();
}
// CheeseBureger.java
public class CheeseBurger extends Burger{
public CheeseBurger(String name) {
super(name);
}
@Override
boolean isDoublePatty() {
return false;
}
}
// BigMacBurger.java
public class BigMacBurger extends Burger {
public BigMacBurger(String name) {
super(name);
}
@Override
boolean isDoublePatty() {
return true;
}
}
// Cola.java
public class Cola extends Beverage {
public Cola(String name, int sugar) {
super(name, sugar);
}
@Override
public void drink() {
System.out.println("코카 콜라를 마십니다.");
}
@Override
public void empty() {
System.out.println("코카 콜라를 다 마셨습니다.");
}
}
//Sprite.java
public class Sprite extends Beverage {
public Sprite(String name, int sugar) {
super(name, sugar);
}
@Override
public void drink() {
System.out.println("사이다를 마십니다.");
}
@Override
public void empty() {
System.out.println("사이다를 다 마셨습니다.");
}
}
// Application 실행
public class Application {
public static void main(String[] args) {
FastFood fastFood = new FastFood(new CheeseBurger("치즈버거"), new Cola("콜라", 100));
fastFood.printName();
System.out.println(fastFood.getBeverageSugar()); // 100
fastFood.setBurger(new BigMacBurger("빅맥"));
fastFood.setBeverage(new Sprite("사이다", 60));
fastFood.printName();
System.out.println(fastFood.getBeverageSugar()); // 60
}
}