'pattern'에 해당되는 글 11건

  1. 2008.08.19 iterator pattern by 파이팅야 1
  2. 2008.08.08 chain of responsibility by 파이팅야 3
  3. 2008.04.25 template method pattern by 파이팅야 2
  4. 2008.04.25 strategy pattern by 파이팅야 1
  5. 2008.04.25 state pattern by 파이팅야 1
  6. 2008.04.21 facade pattern by 파이팅야 3
  7. 2008.04.18 adapter pattern by 파이팅야 2
  8. 2008.04.17 prototype pattern by 파이팅야 2
  9. 2008.04.17 bridge pattern by 파이팅야 1
  10. 2008.04.15 composite pattern by 파이팅야 3

iterator pattern

Pattern 2008. 8. 19. 20:46

. 정의

복합 객체 요소들(aggregate)의 내부 표현 방식을 공개하지 않고도 순차적으로 접근할 수 있는 방법을 제공한다.

 

사용자 삽입 이미지

 

public class Client {

public static void main(String[] args) {

         ArrayListAggregate newList = new ArrayListAggregate();

         newList.add('a');

         newList.add('c');

         newList.add('b');

         newList.add('d');

         IIterator iterator = newList.createIterator();

 

         Object obj = null;

         while(iterator.hasNext()) {

                  obj = iterator.next();

                  System.out.println(obj);

         }

        

         LinkedListAggregate newList2 = new LinkedListAggregate();

         newList2.add(1);

         newList2.add(3);

         newList2.add(2);

         newList2.add(4);

        

         IIterator iterator2 = newList2.createIterator();

 

         while(iterator2.hasNext()) {

                  obj = iterator2.next();

                  System.out.println(obj);

         }

--------------------------------------------------------------------

public interface IAggregate {

         public IIterator createIterator();

--------------------------------------------------------------------

public class ArrayListAggregate implements IAggregate {

         ArrayList arrayList = new ArrayList();

         public IIterator createIterator() {

                  return new ArrayListIterator(this);

         }

         public int size() {

                  return this.arrayList.size();

         }

         public boolean add(Object obj) {

                  return this.arrayList.add(obj);

         }

         public Object get(int index) {

                  return this.arrayList.get(index);

         }

--------------------------------------------------------------------

public class LinkedListAggregate implements IAggregate {

         LinkedList linkedList = new LinkedList();

         public IIterator createIterator() {

                  return new LinkedListIterator(this);

         }

         public int size() {

                  return this.linkedList.size();

         }

         public boolean add(Object obj) {

                  return this.linkedList.add(obj);

         }

         public Object get(int index) {

                  return this.linkedList.get(index);

         }

--------------------------------------------------------------------

public interface IIterator {

         abstract boolean hasNext();

         abstract Object next();

--------------------------------------------------------------------

public class ArrayListIterator implements IIterator {

         ArrayListAggregate aggregate = null;

         int currentIndex = -1;

        

         public ArrayListIterator(ArrayListAggregate arrayListAggregate) {

                  this.aggregate = arrayListAggregate;

         }

         public Object next() {

                  return this.aggregate.get(this.currentIndex);

         }

         public boolean hasNext() {

                  this.currentIndex++;

                  if (this.currentIndex >= this.aggregate.size() ||

                           this.aggregate.get(this.currentIndex) == null)

                           return false;

                  else

                           return true;

         }

--------------------------------------------------------------------

public class LinkedListIterator implements IIterator {

         LinkedListAggregate aggregate = null;

         int currentIndex = -1;

 

         public LinkedListIterator(LinkedListAggregate linkedListAggregate) {

                  this.aggregate = linkedListAggregate;

         }

         public Object next() {

                  return this.aggregate.get(this.currentIndex);

         }

         public boolean hasNext() {

                  this.currentIndex++;

                  if (this.currentIndex >= this.aggregate.size()

                     || this.aggregate.get(this.currentIndex) == null)

                           return false;

                  else

                           return true;

         }

Posted by 파이팅야
,

chain of responsibility

Pattern 2008. 8. 8. 18:41

. 의도

메시지를 보내는 객체와 이를 받아 처리하는 객체들 간의 결합도를 없애기 위한 패턴입니다. 하나의 요청에 대한 처리가 반드시 한 객체에서만 되지 않고, 여러 객체에게 그 처리 기회를 주려는 것입니다.

 

. 예제

logLevel의 값에 따라서 처리가능하면 로그를 쌓고 아니면 다른 객체에게 처리하라고 책임을 넘김

사용자 삽입 이미지

public class Client {

         public static void main(String[] args) {

                  ALog info = new Info();

                  ALog warning = new Warning();

                  ALog debug  = new Debug();

                 

                  // 체인 형성

                  info.setLog(warning);

                  warning.setLog(debug);

                 

                  info.writeLog(-100);

                  info.writeLog(1);

                  info.writeLog(2);

                  info.writeLog(3);

                  info.writeLog(100);

----------------------------------------------------------------

public abstract class ALog {

         public ALog log = null;

         public void setLog(ALog log) {

                  this.log = log;

         }

         abstract void writeLog(int logLevel);

----------------------------------------------------------------

public class Info extends ALog {

         void writeLog(int logLevel) {

                  if(logLevel <= 1) {

                           System.out.println("info log");

                  } else {

                           if (super.log != null)

                                   super.log.writeLog(logLevel);

                  }

         }

----------------------------------------------------------------

public class Warning extends ALog {

         void writeLog(int logLevel) {

                  if(logLevel == 2) {

                           System.out.println("warning log");

                  } else {

                           if (super.log != null)

                                   super.log.writeLog(logLevel);

                  }

         }

----------------------------------------------------------------

public class Debug extends ALog {

         void writeLog(int logLevel) {

                  if (logLevel >= 3) {

                           System.out.println("debug log");

                  } else {

                           if (super.log != null)

                                   super.log.writeLog(logLevel);

                  }

         }

Posted by 파이팅야
,

template method pattern

Pattern 2008. 4. 25. 21:03

template method pattern에서는 메소드에서 알고리즘의 골격을 정의합니다. 알고리즘의 여러 단계 중 일부는 서브클래스에서 구현할 수 있습니다. 템플릿 메소드를 이용하면 알고리즘의 구조는 그대로 유지하면서 서브클래스에서 특정 단계를 재정의할 수 있습니다.

상위 클래스에서 처리의 흐름을 정하고 하위 클래스에서 구체적인 내용을 결정하는 디자인 패턴입니다.

예제)

사용자 삽입 이미지

public abstract class AWorker {

             protected final void work() {

                           attendance();

                           doIt();

                           leave();

             }

             private void attendance() {

                           System.out.println("출근하다.");

             }

             private void leave() {

                           System.out.println("퇴근하다.");

             }

             abstract void doIt();

--------------------------------------------------------------

public class Designer extends AWorker {

             void doIt() {

                           System.out.println("디자인 작업함");

             }

--------------------------------------------------------------

public class Programmer extends AWorker {

             void doIt() {

                           System.out.println("프로그램 작업함");

             }

--------------------------------------------------------------

public class Client {

             public static void main(String[] args) {

                           AWorker worker = null;

                           worker = new Designer();

                           worker.work();

                          

                           worker = new Programmer();

                           worker.work();

             }

--------------------------------------------------------------

출근하다.

디자인 작업함

퇴근하다.

출근하다.

프로그램 작업함

퇴근하다.

Posted by 파이팅야
,

strategy pattern

Pattern 2008. 4. 25. 18:39

Strategy Pattern알고리즘 군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 만든다. 바뀌는 부분을 인터페이스로 분리하여 처리하고, 그 인터페이스의 구현체를 바꿈으로서 로직을 변경한다.

(if or switch문으로 분기되는 부분이 있을 때는 strategy pattern을 고려해 보고, 분기되고 속성의 변화에 의해 행동이 바뀌면 state pattern을 고려해 보면 될 것 같다. 동적으로 type code성인 iGame값이 바뀌어야 할때 이 패턴을 사용해야 겠다. 동적으로 바뀌지 않고 불변이면 상속구조도 괜찮다.)


예제) StarcraftMine게임 하는 부분

사용자 삽입 이미지

public interface IGame {

             void play();

------------------------------------------------------

public class Starcraft implements IGame {

             public void play() {

                           System.out.println("starcraft 게임중...");

             }

------------------------------------------------------

public class Mine implements IGame {

             public void play() {

                           System.out.println("지뢰찾기 게임중");

             }

------------------------------------------------------

public class PCGame {

             private IGame iGame;

             public PCGame(IGame iGame) {

                           this.iGame = iGame;

             }

             public void play() {

                           iGame.play();

             }

             public IGame getIGame() {

                           return iGame;

             }

             public void setIGame(IGame game) {

                           iGame = game;

             }

------------------------------------------------------

public class Client {

             public static void main(String[] args) {

                           PCGame pcGame = new PCGame(new Starcraft());

                           pcGame.play();    // starcraft 게임중...

                          

                           pcGame.setIGame(new Mine());

                           pcGame.play();    // 지뢰찾기 게임중

             }

Posted by 파이팅야
,

state pattern

Pattern 2008. 4. 25. 09:58

State Pattern을 이용하면 객체의 내부 상태가 바뀜에 따라서 객체의 행동을 바꿀 수 있습니다. 마치 객체의 클래스가 바뀌는 것과 같은 결과를 얻을 수 있습니다.

(Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.)

 

State 패턴은 상태(state)를 클래스로 표현한다. 현실세계에서 상태를 사물(object)로 보는 일은 거의 없기 때문에, 상태를 클래스로 표현하는 일은 어색할 수 있다. 그러나, 상태를 클래스로 표현하면 클래스의 교체를 통해서상태의 변화를 나타낼 수 있고, 새로운 상태를 추가해야 하는 경우에는 무엇을 프로그램 하면 되는지 명확해진다.

예제) '마이너스계좌'(MinusAccount)를 사용하는 사용자의 잔금(balance)의 변화에 따라서 계좌의 상태값이 변화한다. Low는 -금액이 되었을때 상태이며 더이상 출금이 안됨, Middle는 0~99사이의 금액일때 상태, High는 100이상의 금액일때 상태이다.

사용자 삽입 이미지

public abstract class AState {

             private double balance;

             private MinusAccount minusAccount;

             public AState(MinusAccount minusAccount) {

                           this.minusAccount = minusAccount;

             }

             protected abstract void deposit(double balance);

             protected abstract void withdraw(double balance);

             Getter/ Setter …

--------------------------------------------------------------------

public class Low extends AState {

             public Low(MinusAccount minusAccount) {

                           super(minusAccount);

             }

             protected void deposit(double balance) {

                           setBalance(getBalance() + balance);

                           if (getBalance() >= 0)

                                        getMinusAccount().setState(
                                            getMinusAccount().getMiddle(), getBalance());

             }

             protected void withdraw(double balance) {

                           System.out.print("*출금불가*,");

             }

--------------------------------------------------------------------

public class Middle extends AState {

             public Middle(MinusAccount minusAccount) {

                           super(minusAccount);

             }

             protected void deposit(double balance) {

                           setBalance(getBalance() + balance);

                           if (getBalance() >= 99)

                                        getMinusAccount().setState(
                                           getMinusAccount().getHigh(), getBalance());

             }

             protected void withdraw(double balance) {

                           setBalance(getBalance() - balance);

                           if (getBalance() < 0)

                                        getMinusAccount().setState(
                                            getMinusAccount().getLow(), getBalance());

             }

--------------------------------------------------------------------

public class High extends AState {

             public High(MinusAccount minusAccount) {

                           super(minusAccount);

             }

             protected void deposit(double balance) {

                           setBalance(getBalance() + balance);

             }

             protected void withdraw(double balance) {

                           setBalance(getBalance() - balance);

                           if (getBalance() < 100)

                                        getMinusAccount().setState(
                                            getMinusAccount().getMiddle(), getBalance());

             }

--------------------------------------------------------------------

public class MinusAccount {

             private Low low;

             private Middle middle;

             private High high;

             private AState state;

            

             public MinusAccount() {

                           low         = new Low(this);

                           middle    = new Middle(this);

                           high       = new High(this);

                           state = middle;

             }

             public void deposit(double balance) {

                           System.out.print("[" + state.getClass().getName() + "],");

                           state.deposit(balance);

                           System.out.println("[" + state.getClass().getName() + "], +"

                                                + balance + ", balance[" + state.getBalance() + "]");

             }

             public void withdraw(double balance) {

                           System.out.print("[" + state.getClass().getName() + "],");

                           state.withdraw(balance);

                           System.out.println("[" + state.getClass().getName() + "], -"

                                                + balance + ", balance[" + state.getBalance() + "]");

             }

Getter/ Setter …

--------------------------------------------------------------------

public class Client {

             public static void main(String[] args) {

                           MinusAccount minusAccount = new MinusAccount();

                           minusAccount.deposit(10); 
                                  // [Middle],[Middle], +10.0, balance[10.0]

                           minusAccount.withdraw(30);             
                                  // [Middle],[Low], -30.0, balance[-20.0]

                           minusAccount.withdraw(5); 
                                  // [Low],*출금불가*,[Low], -5.0, balance[-20.0]

                           minusAccount.deposit(100);             
                                  // [Low],[Middle], +100.0, balance[80.0]

                           minusAccount.deposit(150);             
                                  // [Middle],[High], +150.0, balance[230.0]



구현관련

   - MinusAccount에서 state값을 map으로 들고 있고 map의 key값인 string으로 조회하면 매번 new해서 객체를 생성하지 않아도 될 듯... 아래의 '다른 예' 참고


다른 예




 


Posted by 파이팅야
,

facade pattern

Pattern 2008. 4. 21. 11:02
1. 개요

Facade 패턴은 복잡한 서브 시스템에 통일된 인터페이스를 제공함으로써 복잡한 API를 단순화 시켜준다. 시스템을 서브 시스템 단위로 나누어 구성하는 것은 시스템의 복잡도를 낮춰주지만, 동시에 서브 시스템 사이에서의 통신 부하와 결합도가 증가하게 된다. 이러한 서브 시스템 사이의 의존도를 낮추고, 서브 시스템의 사용자 입장에서 사용하기 편리한 인터페이스를 제공하고자 하는 것이 facade 객체이다.

사용자 삽입 이미지

실생활에서의 고객 서비스 센터와 유사하다. 가령, 어떤 상품을 구매하는 과정에서 문제가 생겼다고 가정할 때, 고객이 문제의 성격에 따라 해당 부서에 직접 연락하는 것이 아니라 고객 서비스 센터를 통하는 것은 Facade 패턴에 대한 좋은 유추 사례가 될 수 있다.

2. 적용 영역

■ 복잡한 서브 시스템에 대해 간단한 인터페이스를 제공하기를 원하는 경우
■ 클라이언트와 인터페이스의 구현 클래스 사이에 의존도가 높은 경우
■ 서브 시스템을 레이어(layer)로 구분하고자 하는 경우


3.
참가자들(participants)
  The classes and/or objects participating in this pattern are:

  • Facade   (MortgageApplication)
    • knows which subsystem classes are responsible for a request.
    • delegates client requests to appropriate subsystem objects.
  • Subsystem classes   (Bank, Credit, Loan)
    • implement subsystem functionality.
    • handle work assigned by the Facade object.
    • have no knowledge of the facade and keep no reference to it.

5. 적용 결과
서브 시스템의 컴포넌트로부터 클라이언트를 격리하여, 클라이언트가 쉽게 서브 시스템을 이용할 수 있다.
서브 시스템과 클라이언트 사이의 의존성을 낮춘다.
■ Facade
패턴을 사용한다고 해도, 필요한 경우 서브 시스템의 클래스에 직접 접근할 수도 있다. , 일반화 정도(generality)와 개발의 편의성 사이에서의 적당한 합의점을 찾아야 한다.

6. 예제

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

 

class FacadeTest extends JFrame
{

 private JFrame frame;
 private JPanel panel;
 private JTextArea MainWindow;
 private JScrollPane sp1;
 private JTextField ChatWindow;
 private JButton SendButton;
 private JTextArea UserWindow;
 private JScrollPane sp2;


 public FacadeTest()

 {
 }

 

 public void createUI()
 {

  setTitle("Facade Test");
  setBounds(0, 0, 467, 260);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


  panel = new JPanel();
  panel.setLayout(null);
  add(panel, BorderLayout.CENTER);
 
  MainWindow = new JTextArea();
  sp1 = new JScrollPane(MainWindow);
  MainWindow.setLineWrap(true);
  MainWindow.setEditable(false);
  sp1.setBounds(5, 5, 300, 198);
  panel.add(sp1);

 

  ChatWindow = new JTextField();
  ChatWindow.setBounds(5, 205, 230, 25);
  panel.add(ChatWindow);

 

  SendButton = new JButton("Send");
  SendButton.setBounds(238, 206, 64, 23);

  panel.add(SendButton);

 

  UserWindow = new JTextArea();
  sp2 = new JScrollPane(UserWindow);
  UserWindow.setEditable(false);
  sp2.setBounds(310, 5, 145, 225);
  panel.add(sp2);

 

  setResizable(false);
  show();

 }

 

 public static void main(String[] args)
 {

FacadeTest facade = new FacadeTest();
facade.createUI();

 }

}

7. 참고

  http://en.wikipedia.org/wiki/Facade_pattern


Posted by 파이팅야
,

adapter pattern

Pattern 2008. 4. 18. 13:15

Adapter Pattern은 특정 클래스의 인터페이스를 클라이언트가 기대하는 다른 인터페이스로 전환시킨다.

인터페이스가 호환되지 않아 상호작용할 수 없는 경우에, Adapter를 이용하여 클래스 사이의 인터페이스의 호환성을 보장 가능함.

 (Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.)

- 새로운 인터페이스로 클래스를 감싸게 되기 때문에 Wrapper 패턴이라고도 함.

- Bridge 패턴은 Object Adapter와 유사한 구조를 갖고 있지만, 서로 의도가 다르다. Adapter는 존재하고 있는 객체에 대한 인터페이스를 바꾸기 위한 의도를 갖지만, Bridge는 인터페이스를 해당 구현체(implementation)분리하기 위한 의도를 띈다

- 아래와 같이 적용하는 패턴의 방법은 2가지가 있다.

1) Class Adapter pattern 

다중상속으로 구현하는 방법. Java에서는 다중상속 안됨. C++에서 사용하면 됨

사용자 삽입 이미지

2) Object Adapter pattern 

Object를 이용해서 구현하는 방법.

(예로 Adapter의 생성자에서 adaptee를 생성해서 Operation1()에서 adaptee.Operation2()를 호출함)

 

사용자 삽입 이미지

ㅇ. 구현 예


ㅇ. 소스

public abstract class Unit {
abstract void move();
abstract void attack();
}
public class Marine extends Unit {
void attack() {
System.out.println("탕탕탕(마린 공격)");
}
void move() {
System.out.println("튀튀 ~~~ (마린 이동)");
}
}
public class Hydralisk extends Unit {
void attack() {
System.out.println("툇!툇!(히드라 침뱉는 소리)");
}
void move() {
System.out.println("엉금 엉금 (히드라 이동)");
}
}
public class Ghost extends Unit {
public Ninja ninja = null;
public Ghost() {
this.ninja = new Ninja();
}
void attack() {
this.ninja.cut();
}
void move() {
this.ninja.walk();
}
}
public class Battlecruiser extends Unit {
public Airwolf airwolf = null;
public Battlecruiser() {
this.airwolf = new Airwolf();
}
void attack() {
this.airwolf.shoot();
}
void move() {
this.airwolf.fly();
}
}
public class Ninja {
public void walk() {
System.out.println("걷기");
}
public void cut() {
System.out.println("자르기");
}
}
public class Airwolf {
public void fly() {
System.out.println("날기");
}
public void shoot() {
System.out.println("총쏘기");
}
}
public class Client {
public static void main(String[] args) {
System.out.println("-- Ghost --");
Unit ghost = new Ghost();
ghost.move();
ghost.attack();
System.out.println("-- Battlecruiser --");
Unit battlecruiser = new Battlecruiser();
battlecruiser.move();
battlecruiser.attack();
}
}

-- Ghost --
걷기
자르기
-- Battlecruiser --
날기
총쏘기

ㅇ. 참고

- wikipedia : 

http://en.wikipedia.org/wiki/Adapter_pattern

- 위키피디아 : 

http://ko.wikipedia.org/wiki/%EC%96%B4%EB%8C%91%ED%84%B0_%ED%8C%A8%ED%84%B4

Posted by 파이팅야
,

prototype pattern

Pattern 2008. 4. 17. 18:00

Prototype Pattern은 클래스로부터 인스턴스를 생성하는 것이 아니라, 인스턴스로부터 인스턴스를 생성하게 된다

(Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype)

- ConcretePrototype 클래스에서 복사본을 생성할 때 단순 복사본(Shallow Copy)을 생성한다는 것을 알 수 있다. 닷넷에서는 단순 복사본을 생성하는 메서드 MemberwiseClone()이 제공된다. Java Clone()이 제공된다.

- 단순 복사본(Shallow Copy)은 원본의 참조를 유지하지만 전체 복사본(Deep Copy)은 원본의 참조를 유지하지 않고 참조되는 객체의 새로운 복사본을 참조한다.

객체 X가 객체 A, B를 참조하고, 객체 A는 객체 M을 참조한다고 할 때 X에 대한 단순 복사본 Y는 객체 A B를 참조한다.Deep Copy new()해서 생성된 것이라 생각하면 쉬울 것 같다.
- 활용성 ==> 인스턴스화할 클래스를 런타임에 지정할 때, 클래스의 인스턴스들이 서로 다른 상태 조합 중에 어느 하나일 때
- 관련 패턴 ==> 추상 팩토리 패턴과는 어떤 면에서 경쟁적인 관계이다. 하지만 함께 사용될 수도 있다. 추상 팩토리 패턴은 원형 집합을 저장하다가 필요할 때 복제하여 제품 객체를 반환하도록 사용할 수도 있다. 복합체 패턴과 장식자 패턴을 많이 사용해야 하는 설계에서 원형 패턴을 사용해서 재미를 볼수도 있다.

사용자 삽입 이미지

public abstract class AColorBase implements Cloneable {

       public abstract AColorBase createClone();

--------------------------------------------------------------

public class Color extends AColorBase {

       private int red;

       private int green;

       private int blue;

 

       public Color(int red, int green, int blue) {

             this.red     = red;

             this.green   = green;

             this.blue    = blue;

       }

       public AColorBase createClone() {

             AColorBase aColorBase = null;

             try {

                    aColorBase =(AColorBase)this.clone();

             } catch (CloneNotSupportedException e) {

                    e.printStackTrace();

             }

             return aColorBase;

       }

       public String toString() {

             return String.format("red[%d], green[%d], blue[%d]", this.red, this.green, this.blue);

       }

       Getter/ Setter …

--------------------------------------------------------------

public class ColorManager {

       private Hashtable<String, AColorBase> colorTable;

       public ColorManager() {

             colorTable = new Hashtable<String, AColorBase>();

       }

       public AColorBase register(String colorName, AColorBase colorBase) {

             return colorTable.put(colorName, colorBase);

       }

       public AColorBase create(String colorName) {

             return colorTable.get(colorName).createClone();

       }

--------------------------------------------------------------

public class Client {

  public static void main(String[] args) {

        // 인스턴스 만들기

        Color green = new Color(0, 200, 0);

        ColorManager colorManager = new ColorManager();

        colorManager.register("red", new Color(200, 0, 0));

        colorManager.register("green", green);

        colorManager.register("blue", new Color(0, 0, 200));

 

        // 외부:인스턴스 만들기, 내부:인스턴스 복사

        // 복사(clone)되기 때문에 생성의 부하가 적음

        AColorBase newColor = colorManager.create("red");

        System.out.println(newColor);

 

        newColor = colorManager.create("green");

        System.out.println(newColor);

--------------------------------------------------------------
red[200], green[0], blue[0]

red[0], green[200], blue[0]


  • 구현 관련
    • 위의 구현형태는 하나의 클래스로부터 상태값이 다른 여러 객체를 생성하고, 생성된 객체들을 복사해서 사용하는 형태이다. 이와 다르게 AColorBase와 같은 Prototype 클래스을 구현하는 여러개의 클래스들의 객체를 각각 생성하고 생성된 객체들을 복사해서 사용해도 된다. 상황에 따라서 적절히 선택해서 구현하면 된다.
    • ColorManager와 같은 Prototype Manager 객체는 register(생성), unRegister(제거), check(확인)와 같은 메소드들을 일반적으로 제공한다.
    • 그림판의 왼쪽에 있는 palette가 ColorManager와 비슷한 형태이고, palette에서 선택한 도형을 그림판에서 생성할때 마다 clone 되어 생성되는 형태이다. 사용자에 의해 실시간으로 도형을 생성하기 위해서는 palette와 같은 형태의 class가 있어야 한다. 예를 들면 사용자에 의해 선택된 2가지의 도형을 합친 새로운 도형을 만들고자 하면 palette에 두가지 도형에 대해 composite pattern을 사용해서 등록하고 사용하면 된다.
    • 참고

Posted by 파이팅야
,

bridge pattern

Pattern 2008. 4. 17. 11:02


  • 개요
    • 추상화 부분과 구현 부분을 분리시켜 서로 독립적으로 확장 가능하게 한다. (Decouple an abstraction from its implementation so that the two can vary independently)
    • 아래의 Class Digram에서 추상화 부분은 AProgram, Program 부분이고 구현 부분은 Aalgorithm, Algorithm1, Algorithm2 부분이다. Client는 추상화 부분만 알게되고 실제적으로 내부구현 부분이 있는 구현 부분에 대해서는 모르게 된다. 따라서 구현 부분이 바뀌어도 Client에 제공되는 추상화 interface 부분은 변경이 없다.
    • ProgramA와 ProgramB가 Algorithm1이나 Algorithm2에 따라서 다르게 동작하는 경우(리모콘이 있는데 여러 TV제품사 별로 채널변경하는 기능이 다른 경우, SearchEngine이 있는데 OS별로 Search방법이 다른 경우)에 client에게 interface를 담당하는 Program부분과 실제로 처리하는 로직 및 비즈니스를 구현하는 Algorithm를 서로 분리해서 독립적으로 확장 가능하게 한다. 만약 이런 구조가 아니면 AProgram을 구현하는 Algorithm1ProgramA, Algorithm2ProgramB와 같이 구현되는 형태가 되므로 class들이 많이 증가하게 되므로 추가 및 수정에 용이하지 않다.
  • 문제 예

  • 소스
public abstract class Aalgorithm {
abstract int calculate(int num);
}
public class Algorithm1 extends Aalgorithm {
int calculate(int num) {
return (num + 2) * 10;
}
}
public class Algorithm2 extends Aalgorithm {
int calculate(int num) {
return (num - 1) + 200 * 123;
}
}
public abstract class AProgram {
int num = 0;
Aalgorithm algorithm = null;
public AProgram(int num, Aalgorithm algorithm) {
this.num = num;
this.algorithm = algorithm;
}
public abstract int cal();
}
public class Program extends AProgram {
public Program(int num, Aalgorithm algorithm) {
super(num, algorithm);
}
public int cal() {
return this.algorithm.calculate(this.num);
}
}
public class Client {
public static void main(String[] args) {
AProgram prog1 = new Program(2, new Algorithm1());
AProgram prog2 = new Program(5, new Algorithm2());

int result1 = prog1.cal();
int result2 = prog2.cal();
System.out.println("result1[" + result1 + "]");
System.out.println("result2[" + result2 + "]");
}
}
-------------------------
result1[40]
result2[24604]

  • 구현 관련
    • Program 부분을 Template Class 형태로 변경하면 Client에서 다음과 같이 사용할 수도 있다. (아래의 '위키피디아' 링크의 내용 중 '이름을 사용한 c#'부분의 내용 참고)
      • AProgram prog1 = new Program<Algorithm1>(2);
      • AProgram prog2 = new Program<Algorithm2>(2);
    •  AProgram에서 다음과 같이 수정하게 되고 Program에서는 algorithm의 값을 바로 사용하는 형태가 되면, 추후 algorithm이 추가될때 마다 소스를 수정해 줘야 하는 단점이 있다. 차라리 Abstract Factory나 Factory Method를 사용해도 될것 같다.
      • 변경 전  : Aalgorithm algorithm = null;
      • 변경 후 : 
        • #ifdef _ALG1
          • Aalgorithm algorithm = new Algorithm1();
        • #else
          • Aalgorithm algorithm = new Algorithm2();
        • #end if
    • Progam에서 num값이 10 이상이면 algorithm1이 실행되고, 10미만이면 algorithm2가 실행되게 사용할 수 있다.
  • 차이점
    • Adapter Pattern 은 이미 존재하는 객체를 이용해서 다른 객체의 인터페이스를 만들어 주기 위한 목적으로 쓰이나, Bridge패턴은 추상화 부분과 구현 부분을 분리해서 독립적으로 확장하고자 하기 위한것이다. 즉 Bridge Pattern은 분리를 할려고 하고 Adapter는 재활용 할려고 한다.

  • 참고


Posted by 파이팅야
,

composite pattern

Pattern 2008. 4. 15. 21:02

Composite 패턴은 부분에서 전체에 이르는 계층 구조를 구축하거나 Tree형 자료 명세 내역을 생성하기 위해 사용될 수 있다. 

예를 들어 폴더와 파일을 합해서 [폴더 엔트리]로 취급하듯이 그릇과 내용물을 같은 종류로 취급하는 경우다. 이와 같이 특정 [객체들](파일)[그것들을 포함하는 객체들](폴더)을 동일하게 다룰 수 있게 해주는 패턴 Composite 패턴이라고 한다.

 

 File는 아무것도 포함할 수 없고 포함되는 역할을 하며, Folder는 File이나, 다른 Folder를 포함 할 수 있다. File의 operation()과 Folder의 operation()은 각각 다르게 동작한다.
(만약 HTML Parser를 구현한다면 Folder=Element, File=Attribute가 될 것이다.)
사용예) HTML DOM, XML

사용자 삽입 이미지


 

public abstract class AComponent {

             private String name;

             public String getName() {…}

             public void setName(String name) {…}

 

             protected abstract void operation(int depth);

             protected abstract void add(AComponent aComponent);

             protected abstract void remove(AComponent aComponent);

---------------------------------------------------------------------------

public class File extends AComponent {

             public File(String name) {

                           super.setName(name);

             }

             protected void operation(int depth) {

                           for (int i = 0; i < depth; i++)

                                        System.out.print("-");

                           System.out.println(" " + super.getName());

             }

             protected void add(AComponent component) {}

             protected void remove(AComponent component) {}
---------------------------------------------------------------------------

public class Folder extends AComponent {

             private List<AComponent> componentList = null;

             public Folder(String name) {

                           super.setName(name);

                           componentList = new ArrayList<AComponent>();

             }

             protected void operation(int depth) {
                           // 폴더의 이름을 출력함

                           for (int i = 0; i < depth; i++)                                    

                                        System.out.print("-");

                           System.out.println("+" + super.getName());

                           // 해당 폴더안의 자식들을 출력함
                          
for (AComponent c : this.componentList)

                                        c.operation(depth + 2);

             }

             protected void add(AComponent component) {

                           componentList.add(component);

             }

             protected void remove(AComponent component) {

                           componentList.remove(component);

             }

---------------------------------------------------------------------------

public class Client {

             public static void main(String[] args) {

                           Folder root = new Folder("ROOT");

                           root.add(new File("a"));

                           root.add(new File("b"));

                          

                           Folder sub1 = new Folder("SUB1");

                           sub1.add(new File("c"));

                           sub1.add(new File("d"));

                           root.add(sub1);

                          

                           root.add(new File("e"));

                          

                           root.operation(1);

             }

---------------------------------------------------------------------------

[실행결과]

-+ROOT

--- a

--- b

---+SUB1

----- c

----- d
--- e

Posted by 파이팅야
,