컴파운드 패턴
Written by niee on
컴파운드 패턴이란?
반복적으로 생길 수 있는 일반적인 문제를 해결하기 위한 용도로 두 개 이상의 패턴을 결합해서 사용하는 것. 패턴을 같이 쓴다고 무조건 컴파운드 패턴은 아니다. 문제를 해결하기 위한 용도로 사용해야 된다. 대표적인 컴파운드 패턴은 MVC이다.
//Quckable인터페이스를 구현한 클래스들
public interface Quackable {
public void quack();
}
public class DuckCall implements Quackable{
@Override
public void quack() {
System.out.println("Kwak");
}
}
public class MallardDuck implements Quackable {
@Override
public void quack() {
System.out.println("Quack");
}
}
public class RedheadDuck implements Quackable {
@Override
public void quack() {
System.out.println("quack");
}
}
public class RubberDuck implements Quackable{
@Override
public void quack() {
System.out.println("Squeak");
}
}
- 실행
public class DuckSimulator {
public static void main(String [] args) {
DuckSimulator simulator = new DuckSimulator();
simulator.simulator();
}
void simulator() {
Quackable mallardDuck = new MallardDuck();
Quackable redheadDuck = new RedheadDuck();
Quackable duckCall = new DuckCall();
Quackable rubberDuck = new RubberDuck();
System.out.println("\nDuck Simulator");
simulator(mallardDuck);
simulator(redheadDuck);
simulator(duckCall);
simulator(rubberDuck);
}
void simulator(Quackable duck) {
duck.quack();
}
}
---------------------------------
Duck Simulator
Quack
quack
Kwak
Squeak
- 거위가 추가되었다.
public class Goose {
public void honk() {
System.out.println("Honk");
}
}
-
Duck를 집어 넣을 수 있는 곳이라면 어디든지 Goose도 집어 넣을 수 있어야 한다고 가정한다. 하지만 클래스가 다른데 거위를 시뮬레이터에 집어 넣어야 한다. 어떻게 해야 거위를 오리와 어울리게 할 수 있을까??
-
거위용 어댑터를 만들면 된다.
public class GooseAdapter implements Quackable {
Goose goose;
public GooseAdapter(Goose goose) {
this.goose = goose;
}
@Override
public void quack() {
goose.honk();
}
}
//DuckSimulator
Quackable gooseDuck = new GooseAdapter(new Goose());
어댑터 패턴(Adapter Pattern)의 정의
- 한 클래스(어떤)의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환한다. 어탭터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있습니다.
-
어댑터는 클라이언트로부터 요청을 받아서 새로운 업체에서 제공하는 클래스에서 받아들일 수 있는 형태의 요청으로 변환시켜주는 중개인 역할을 한다.
- 꽥소리를 낸 횟수를 세주는 기능을 추가해야 한다.
- 어떻게 해야할까??
- 소리의 횟수를 세는 기능을 가진 데코레이터 객체를 만들어서 오리 객체들을 감싸면 된다. 그러면 Duck객체들을 건드리지 않아도 된다.
//데코레이터 객체
public class QuackCounter implements Quackable{
Quackable duck;
static int numberOfQuacks;
public QuackCounter(Quackable duck) {
this.duck = duck;
}
@Override
public void quack() {
duck.quack();
numberOfQuacks++;
}
public static int getQuacks() {
return numberOfQuacks;
}
}
//실행
public class DuckSimulator {
public static void main(String [] args) {
DuckSimulator simulator = new DuckSimulator();
simulator.simulator();
}
void simulator() {
Quackable mallardDuck = new QuackCounter(new MallardDuck());
Quackable redheadDuck = new QuackCounter(new RedheadDuck());
Quackable duckCall = new QuackCounter(new DuckCall());
Quackable rubberDuck = new QuackCounter(new RubberDuck());
Quackable gooseDuck = new GooseAdapter(new Goose());
System.out.println("\nDuck Simulator");
simulator(mallardDuck);
simulator(redheadDuck);
simulator(duckCall);
simulator(rubberDuck);
simulator(gooseDuck);
System.out.println("The Ducks quacked " + QuackCounter.getQuacks() + " times");
}
void simulator(Quackable duck) {
duck.quack();
}
}
-----------------------------
Duck Simulator
Quack
quack
Kwak
Squeak
Honk
The Ducks quacked 4 times
Decorator Pattern의 정의
- 데코레이터 패턴에서는 객체에 추가적인 요건을 동적으로 첨가한다. (즉 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 것 외에 원하는 추가적인 작업을 수행할 수 있다.)
- 데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.
- 한마디로 기존 구현되어있는 클래스에 기능을 추가하기위한 패턴이다.
- 새로운 문제점
- 데코레이터를 쓸 때는 객체들을 제대로 포장하지 않으면 원하는 행동을 추가할 수 없다.
- 그렇다면 오리 객체를 생성하는 작업을 한 군데에 몰아서 하는건 어떨까? 오리를 생성하고 데코레이터로 감싸는 부분을 따로 빼내서 캡슐화를 하자.
- 모든 오리들이 데코레이터로 감싸지도록 할 수 있는 방법이 필요하다. 그렇게 하는 데는 팩토리를 만드는게 제격이다. 이 팩토리에서는 여러 종류의 오리들을 생산해야 할 테니깐 추상 팩토리 패턴을 사용하자
public abstract class AbstractDuckFactory {
public abstract Quackable createMallardDuck();
public abstract Quackable createRedheadDuck();
public abstract Quackable createDuckCall();
public abstract Quackable createRubberDuck();
}
public class CountingDuckFactory extends AbstractDuckFactory{
@Override
public Quackable createMallardDuck() {
return new QuackCounter(new MallardDuck());
}
@Override
public Quackable createRedheadDuck() {
return new QuackCounter(new RedheadDuck());
}
@Override
public Quackable createDuckCall() {
return new QuackCounter(new DuckCall());
}
@Override
public Quackable createRubberDuck() {
return new QuackCounter(new RubberDuck());
}
}
public class DuckSimulator {
public static void main(String [] args) {
DuckSimulator simulator = new DuckSimulator();
AbstractDuckFactory duckFactory = new CountingDuckFactory();
simulator.simulator(duckFactory);
}
void simulator(AbstractDuckFactory duckFactory) {
Quackable mallardDuck = duckFactory.createMallardDuck();
Quackable redheadDuck = duckFactory.createRedheadDuck();
Quackable duckCall = duckFactory.createDuckCall();
Quackable rubberDuck = duckFactory.createRubberDuck();
Quackable gooseDuck = new GooseAdapter(new Goose());
System.out.println("\nDuck Simulator");
simulator(mallardDuck);
simulator(redheadDuck);
simulator(duckCall);
simulator(rubberDuck);
simulator(gooseDuck);
System.out.println("The Ducks quacked " + QuackCounter.getQuacks() + " times");
}
void simulator(Quackable duck) {
duck.quack();
}
}
추상 팩토리 (Abstract Factory)
구체적인 클래스를 지정하지 않고 관련성을 갖는 객체들의 집합을 생성하거나 서로 독립적인 객체들의 집합을 생성할 수 있는 인터페이스를 제공한다.
Comments