Visitor 복합객체의 연산을 수행하는 객체

알고리즘을 객체의 구조에서 분리시킨다.

-- 객체의 구조를 수정하지 않고도 실질적으로 새로운 동작을 객체 구조에 추가시킬 수 있다.

-- 컬렉션의 구조를 변하지 않고도 기능을 추가 가능하다.

-- Java에서는 Visitor Pattern을 고려하여서 사용해야 한다.

 - Composite Pattern과 연계하여 사용하는 경우가 많다.


  1. interface IVisitor<E> {
  2.         void visit(E e);
  3. }
  4.  
  5. // 방문자 허용 인터페이스
  6. interface IAcceptor<E> {
  7.         void accept(IVisitor<E> v);
  8. }
  9.  
  10. class Node<E> {
  11.         public final E data;
  12.         public final Node<E> next;
  13.  
  14.         public Node(E data, Node<E> next) { // Object
  15.                 this.data = data;
  16.                 this.next = next;
  17.         }
  18.  
  19. }
  20.  
  21. class SList<E> implements Iterable<E>, IAcceptor<E> {
  22.         private Node<E> head;
  23.  
  24.         public SList() {
  25.                 head = null;
  26.         }
  27.  
  28.         public void addFront(E n) {
  29.                 head = new Node<E>(n, head);
  30.         }
  31.  
  32.         public E front() {
  33.                 return head.data;
  34.         }
  35.  
  36.         @Override
  37.         public Iterator<E> iterator() {
  38.                 return new SListIterator<E>(head);
  39.         }
  40.  
  41.         // 외부로 노출되지 않기 위해 private class 로 구현하는게 일반적이다.
  42.         @SuppressWarnings("hiding")
  43.         private class SListIterator<E> implements Iterator<E> {
  44.                 private Node<E> current;
  45.  
  46.                 public SListIterator(Node<E> node) {
  47.                         this.current = node;
  48.                 }
  49.  
  50.                 @Override
  51.                 public boolean hasNext() {
  52.                         return current != null;
  53.                 }
  54.  
  55.                 // 현재의 요소를 반환하며 다음으로 이동
  56.                 @Override
  57.                 public E next() {
  58.                         E value = current.data;
  59.                         current = current.next;
  60.                         return value;
  61.                 }
  62.  
  63.                 @Override
  64.                 public void remove() {
  65.                         // 지원하지 않음
  66.                         throw new UnsupportedOperationException("remove() unsupported!");
  67.                 }
  68.  
  69.         }
  70.  
  71.         @Override
  72.         public void accept(IVisitor<E> v) {
  73.                 Node<E> current = head;
  74.                 while (current != null) {
  75.                         v.visit(current.data);
  76.                         current = current.next;
  77.                 }
  78.         }
  79. }
  80.  
  81. class MovePointVisitor implements IVisitor<Point> {
  82.  
  83.         private int ax;
  84.         private int ay;
  85.  
  86.         public MovePointVisitor(int ax, int ay) {
  87.                 this.ax = ax;
  88.                 this.ay = ay;
  89.         }
  90.  
  91.         @Override
  92.         public void visit(Point e) {
  93.                 e.move(this.axthis.ay);
  94.         }
  95.  
  96. }
  97.  
  98. class Point {
  99.         private int x;
  100.         private int y;
  101.  
  102.         public Point(int x, int y) {
  103.                 this.x = x;
  104.                 this.y = y;
  105.         }
  106.  
  107.         public void move(int ax, int ay) {
  108.                 this.x += ax;
  109.                 this.y += ay;
  110.                 System.out.println(this.toString());
  111.         }
  112.  
  113.         @Override
  114.         public String toString() {
  115.                 return "Point [x=" + x + ", y=" + y + "]";
  116.         }
  117.  
  118. }
  119.  
  120. // 다형성을 지원하지 않는다.
  121.  
  122. class ShowElementVisitor<extends Point> implements IVisitor<E> {
  123.  
  124.         @Override
  125.         public void visit(E e) {
  126.                 e.move(1010); // 강하게 결합된다.
  127.                 System.out.println(e.toString());
  128.         }
  129.  
  130. }
  131.  
  132. class MyPoint extends Point {
  133.         private int z;
  134.  
  135.         public MyPoint(int x, int y, int z) {
  136.                 super(x, y);
  137.                 this.z = z;
  138.         }
  139.  
  140.         @Override
  141.         public String toString() {
  142.                 return "MyPoint [z=" + z + "]";
  143.         }
  144.  
  145. }
  146.  
  147. //class MuliplyVisitor<E extends Integer> implements IVisitor<E> {
  148. //
  149. //      @Override
  150. //      public void visit(E e) {
  151. //              System.out.println(e * 2); // 한계가 있다. 다형성 구현
  152. //      }
  153. //     
  154. //}
  155. public class Ex3 {
  156.  
  157.         public static void main(String[] args) {
  158.                 SList<Point> points = new SList<>();
  159.                 points.addFront(new Point(1040));
  160.                 points.addFront(new Point(2040));
  161.                 points.addFront(new Point(3030));
  162.                 points.addFront(new Point(4020));
  163.                 points.addFront(new Point(5010));
  164.  
  165.                 for (Point point : points) {
  166.                         point.move(-10-10);
  167.                 }
  168.  
  169.                 points.accept(new MovePointVisitor(1010));
  170.  
  171.                 points.accept(new ShowElementVisitor<Point>());
  172.  
  173.                 SList<MyPoint> myPoints = new SList<>();
  174.                 myPoints.addFront(new MyPoint(10401));
  175.                 myPoints.addFront(new MyPoint(20402));
  176.                 myPoints.addFront(new MyPoint(30303));
  177.                 myPoints.addFront(new MyPoint(40204));
  178.                 myPoints.addFront(new MyPoint(50105));
  179.  
  180.         }
  181.  
  182. }


Chain of Responsibility 책임 전가 패턴

 - 요청이 발생했을때, 첫번째 객체가 요청을 처리하지 못할 경우 다음 객체에게 요청을 전달한다.

 - 요청이 처리될 때까지 고리를 따라 요청을 전달하는 패턴.


  1. abstract class Logger {
  2.         public static int ERR = 3;
  3.         public static int NOTICE = 5;
  4.         public static int DEBUG = 7;
  5.  
  6.         protected int mask;
  7.         protected Logger next;
  8.  
  9.         public void setNext(Logger log) {
  10.                 next = log;
  11.         }
  12.  
  13.         public void message(String msg, int priority) {
  14.                 // 권한이 있으면 처리하고 메시지를 다음(next) 로거에게 넘긴다.
  15.                 if (priority <= mask) {
  16.                         writeMessage(msg);
  17.                 }
  18.                 if (next != null) {
  19.                         next.message(msg, priority);
  20.                 }
  21.         }
  22.  
  23.         abstract protected void writeMessage(String msg);
  24.  
  25.         // private static final Logger INSTANCE = new Logger();
  26.         public static Logger createChain() {
  27.                 Logger logger = new StdoutLogger(Logger.DEBUG);
  28.                 // 처리하지 못하면 다음으로 책임을 넘긴다.
  29.                 Logger logger1 = new EmailLogger(Logger.NOTICE);
  30.                 logger.setNext(logger1);
  31.                 Logger logger2 = new StderrLogger(Logger.ERR);
  32.                 logger1.setNext(logger2);
  33.                 return logger;
  34.         }
  35.  
  36. }
  37.  
  38. class StdoutLogger extends Logger {
  39.         public StdoutLogger(int mask) {
  40.                 this.mask = mask;
  41.         }
  42.  
  43.         @Override
  44.         protected void writeMessage(String msg) {
  45.                 System.out.println("Writing to stdout : " + msg);
  46.         }
  47. }
  48.  
  49. class EmailLogger extends Logger {
  50.         public EmailLogger(int mask) {
  51.                 this.mask = mask;
  52.         }
  53.  
  54.         @Override
  55.         protected void writeMessage(String msg) {
  56.                 System.out.println("Sending to via email : " + msg);
  57.         }
  58.  
  59. }
  60.  
  61. class StderrLogger extends Logger {
  62.         public StderrLogger(int mask) {
  63.                 this.mask = mask;
  64.         }
  65.  
  66.         @Override
  67.         protected void writeMessage(String msg) {
  68.                 System.out.println("Writing to err : " + msg);
  69.  
  70.         }
  71. }
  72.  
  73. public class Ex1 {
  74.  
  75.         public static void main(String[] args) {
  76.                 Logger logger = Logger.createChain();
  77.                 logger.message("Entering function y.", Logger.DEBUG);
  78.                 logger.message("Step 1 completed. ", Logger.NOTICE);
  79.                 logger.message("An error has occured.", Logger.ERR);
  80.         }
  81.  
  82. }


'java > design_pattern' 카테고리의 다른 글

Iterator Pattern - 열거자  (0) 2014.07.01
Visitor Pattern - 방문자 패턴  (0) 2014.07.01
MediatorPattern - 중재자 패턴  (0) 2014.07.01
ObserverPattern - 관찰자 패턴  (0) 2014.07.01
Factory method pattern  (0) 2014.06.27

Mediator (중재자) 패턴. 클래스의 복잡도가 증가하면 중재자를 만들어 구현. 

 객체간의 M:N 관계를 중재자를 두어 1:1로 만들어준다.

 장점 : 객체간의 관계 코드가 중재자 클래스안에 집중됨으로 관리가 편해진다.

 ex)통보센터는 잘 만들어진 중재자 패턴의 예이다.


  1. interface IMediator {
  2.         void sendEvent(String name, String event);
  3. }
  4.  
  5. class Mediator implements IMediator {
  6.         private List<Colleague> colleagues = new ArrayList<>();
  7.  
  8.         public Mediator() {
  9.         }
  10.  
  11.         public void addColleague(Colleague a) {
  12.                 a.setMediator(this);
  13.                 colleagues.add(a);
  14.         }
  15.  
  16.         @Override
  17.         public void sendEvent(String name, String event) {
  18.                 for (Colleague s : colleagues) {
  19.                         if (s.getName() == name) {
  20.                                 s.receiveEvent(name, event);
  21.                         }
  22.                 }
  23.                 // 기존의 복잡성 증가의 코드
  24.                 // switch (name) {
  25.                 // case "A":
  26.                 // a.receiveEvent(name, event);
  27.                 // break;
  28.                 // case "B":
  29.                 // b.receiveEvent(name, event);
  30.                 // break;
  31.                 // case "C":
  32.                 // c.receiveEvent(name, event);
  33.                 // break;
  34.                 // }
  35.         }
  36.  
  37. }
  38.  
  39. // GoF 의 패턴에서는 A,B,C를 협력자 (Colleague)라는 용어로 지칭한다.
  40. abstract class Colleague {
  41.         public IMediator mediator;
  42.  
  43.         public void setMediator(IMediator im) {
  44.                 this.mediator = im;
  45.         }
  46.  
  47.         public void sendEvent(String name, String event) {
  48.                 mediator.sendEvent(name, event);
  49.         }
  50.  
  51.         abstract public void fireEvent(String event);
  52.  
  53.         abstract public void receiveEvent(String name, String event);
  54.  
  55.         abstract public String getName();
  56. }
  57.  
  58. class A extends Colleague {
  59.         String name = "A";
  60.  
  61.         public void fireEvent(String event) {
  62.                 mediator.sendEvent(name, event);
  63.         }
  64.  
  65.         public void receiveEvent(String name, String event) {
  66.                 System.out.println("Receive event from " + name);
  67.         }
  68.  
  69.         public String getName() {
  70.                 return name;
  71.         }
  72. }
  73.  
  74. class B extends Colleague {
  75.         String name = "B";
  76.  
  77.         public void fireEvent(String event) {
  78.                 mediator.sendEvent(name, event);
  79.         }
  80.  
  81.         public void receiveEvent(String name, String event) {
  82.                 System.out.println("Receive event from " + name);
  83.         }
  84.  
  85.         public String getName() {
  86.                 return name;
  87.         }
  88. }
  89.  
  90. class C extends Colleague {
  91.         String name = "C";
  92.  
  93.         public void fireEvent(String event) {
  94.                 mediator.sendEvent(name, event);
  95.         }
  96.  
  97.         public void receiveEvent(String name, String event) {
  98.                 System.out.println("Receive event from " + name);
  99.         }
  100.  
  101.         public String getName() {
  102.                 return name;
  103.         }
  104. }
  105.  
  106. public class Ex2 {
  107.  
  108.         public static void main(String[] args) {
  109.                 A a = new A();
  110.                 B b = new B();
  111.                 C c = new C();
  112.  
  113.                 Mediator m = new Mediator();
  114.                 m.addColleague(a);
  115.                 m.addColleague(b);
  116.                 m.addColleague(c);
  117.  
  118.                 m.sendEvent("B""Hello");
  119.                 a.fireEvent("ReceiveMail");
  120.         }
  121.  
  122. }


'java > design_pattern' 카테고리의 다른 글

Visitor Pattern - 방문자 패턴  (0) 2014.07.01
Chain of Responsibility Pattern - 책임의 전가  (0) 2014.07.01
ObserverPattern - 관찰자 패턴  (0) 2014.07.01
Factory method pattern  (0) 2014.06.27
Flyweight Pattern  (0) 2014.06.27

Observer Pattern

 - 관찰자(Observer), 대상자(Subject)

Subject 에서 Observer에 데이터를 전달하는 2가지 방식

 1. Push -> Subject가 Observer에게 전달하는 방식

 2.  Pull -> Observer가 Subject로 부터 직접 꺼내가는 방식


  1. // Pull 방식
  2. abstract class IObserver {
  3.         private Subject subject;
  4.  
  5.         public Subject getSubject() {
  6.                 return subject;
  7.         }
  8.  
  9.         public abstract void update(Object arg);
  10.  
  11.         public void setSubject(Subject ib) {
  12.                 subject = ib;
  13.         }
  14. }
  15.  
  16. abstract class Subject {
  17.         List<IObserver> observers = new ArrayList<>();
  18.  
  19.         public Subject() {
  20.                
  21.         }
  22.         public void addObserver(IObserver ib) {
  23.                 observers.add(ib);
  24.                 ib.setSubject(this);
  25.         }
  26.  
  27.         public void removeObjserver(IObserver ib) {
  28.                 observers.remove(ib);
  29.         }
  30.  
  31.  
  32.         public void notifyDataSetChanged(Object data) {
  33.                 for (IObserver e : observers) {
  34.                         e.update(data);
  35.                 }
  36.         }
  37.  
  38.         public abstract boolean edit();
  39. }
  40.  
  41. class BarGraph extends IObserver {
  42.  
  43.         @Override
  44.         public void update(Object arg) {
  45.                 int[] data = (int[]) arg;
  46.                 System.out.println("########### Bar Graph ############");
  47.                 for (int i = 0; i < data.length; i++) {
  48.                         System.out.println(+ " : " + data[i]);
  49.                 }
  50.         }
  51.  
  52. }
  53. class CircleGraph extends IObserver {
  54.        
  55.         @Override
  56.         public void update(Object arg) {
  57.                 int[] data = (int[]) arg;
  58.                 System.out.println("########### Circle Graph ############");
  59.                 for (int i = 0; i < data.length; i++) {
  60.                         System.out.println(+ " : " + data[i]);
  61.                 }
  62.         }
  63.        
  64. }
  65.  
  66. class PieGraph extends IObserver {
  67.  
  68.         @Override
  69.         public void update(Object arg) {
  70.                 int[] data = (int[]) arg;
  71.                 // Pull 방식
  72.                 // Subject가 변겨오디었을 경우 표에서 data를 끌어와야한다.
  73.                 // Subject의 참조를 얻어낸다.
  74.                 Table table = (Table) getSubject(); // 강하게 결합된다.
  75.                 // 단점 : 캐스팅이 필요하다.
  76.                 // 장점 : Table의 모든 메소드를 호출 가능하므로
  77.                 // data를 인자로 전달 받을 때 마다 훨씬ㄷ ㅓ많은 정보를 얻어낼 수 있다.
  78.                 // 강하게 결합된다.
  79.                 // 디자인 측면에서 좋지 않다.
  80.                 // Push 방식이 더 선호된다.
  81.                 System.out.println("########### Pie Graph ############");
  82.                 for (int i = 0; i < data.length; i++) {
  83.                         System.out.println(+ " : " + table.getCellValue(i));
  84.                 }
  85.         }
  86.  
  87. }
  88.  
  89. class Table extends Subject {
  90.         private Scanner scan;
  91.         int[] data = { 00000 };
  92.         public int getCellValue(int index) {
  93.                 return data[index];
  94.         }
  95.  
  96.         public boolean edit() {
  97.                 scan = new Scanner(System.in);
  98.                 System.out.println("Index >>");
  99.                 int idx = scan.nextInt();
  100.                 if (idx == 99) {
  101.                         return false;
  102.                 }
  103.                 System.out.println("Data >>");
  104.                 data[idx] = scan.nextInt();
  105.  
  106.                 notifyDataSetChanged(data);
  107.                 return true;
  108.         }
  109. }
  110.  
  111. public class Ex2 {
  112.  
  113.         public static void main(String[] args) {
  114.                 Table table = new Table();
  115.                 table.addObserver(new PieGraph());
  116.                 table.addObserver(new BarGraph());
  117.                 while (table.edit()) {
  118.                 }
  119.         }
  120.  
  121. }


'java > design_pattern' 카테고리의 다른 글

Chain of Responsibility Pattern - 책임의 전가  (0) 2014.07.01
MediatorPattern - 중재자 패턴  (0) 2014.07.01
Factory method pattern  (0) 2014.06.27
Flyweight Pattern  (0) 2014.06.27
Prototype Pattern  (0) 2014.06.27

// 공통성 -> 가변성

// 메소드 / 클래스

//Static factory

//생성자 오버로딩 한계

//좋은 이름

//객체의 생성 제한

//내부객체 리턴 (서브타입)

//idiom 관련 접근


//Abstract factory (추상팩토리) design pattern.

//추상적인 부품을 조합하여 추상적인 제품을 만드는 설계

//설계적 관점 접근

//생성자를 대체하기 위해 만든 Idiom

//객체의 생성 제한

//내부객체를 리턴 가능(서브타입)


//Factory method

// 객체 생성단계만 제외하고 나머지가 유사하다면, 

// 그 메소드는 부모로 옮기고 객체생성은 자식이 맡도록 한다.

// 생성에 관여한 관점


  1. abstract class BaseDialog implements IFactory {
  2.         void init() {
  3.                 IButton button = createButton();
  4.                 IEditBox editBox = createEditBox();
  5.                
  6.                 button.draw();
  7.                 editBox.draw();
  8.         }
  9.         public abstract IButton createButton();
  10.        
  11.         public abstract IEditBox createEditBox();
  12. }
  13. class GTKDialog extends BaseDialog {
  14.         @Override
  15.         public IButton createButton() {
  16.                 return new GTKButton();
  17.         }
  18.        
  19.         @Override
  20.         public IEditBox createEditBox() {
  21.                 return new GTKEditBox();
  22.         }
  23. }
  24. class XPDialog extends BaseDialog {
  25.         @Override
  26.         public IButton createButton() {
  27.                 return new XPButton();
  28.         }
  29.  
  30.         @Override
  31.         public IEditBox createEditBox() {
  32.                 return new XPEditBox();
  33.         }
  34. }
  35. interface IFactory {
  36.         IButton createButton();
  37.  
  38.         IEditBox createEditBox();
  39. }
  40.  
  41. class XPFactory implements IFactory {
  42.  
  43.         @Override
  44.         public IButton createButton() {
  45.                 return new XPButton();
  46.         }
  47.  
  48.         @Override
  49.         public IEditBox createEditBox() {
  50.                 return new XPEditBox();
  51.         }
  52.  
  53. }
  54.  
  55. class GTKFactory implements IFactory {
  56.  
  57.         @Override
  58.         public IButton createButton() {
  59.                 return new GTKButton();
  60.         }
  61.  
  62.         @Override
  63.         public IEditBox createEditBox() {
  64.                 return new GTKEditBox();
  65.         }
  66.  
  67. }
  68.  
  69. interface IButton {
  70.         public void draw();
  71. }
  72.  
  73. interface IEditBox {
  74.         public void draw();
  75. }
  76. class XPEditBox implements IEditBox {
  77.  
  78.         @Override
  79.         public void draw() {
  80.                 System.out.println("draw XP editbox");
  81.         }
  82.  
  83. }
  84.  
  85. class GTKEditBox implements IEditBox {
  86.  
  87.         @Override
  88.         public void draw() {
  89.                 System.out.println("draw GTK editbox");
  90.         }
  91.  
  92. }
  93.  
  94. class XPButton implements IButton {
  95.         @Override
  96.         public void draw() {
  97.                 System.out.println("draw XP button");
  98.         }
  99. }
  100.  
  101. class GTKButton implements IButton {
  102.         @Override
  103.         public void draw() {
  104.                 System.out.println("draw GTK button");
  105.         }
  106. }


'java > design_pattern' 카테고리의 다른 글

MediatorPattern - 중재자 패턴  (0) 2014.07.01
ObserverPattern - 관찰자 패턴  (0) 2014.07.01
Flyweight Pattern  (0) 2014.06.27
Prototype Pattern  (0) 2014.06.27
State Pattern  (0) 2014.06.27

// Fly Weight Design Pattern

// 속성이 동일한 객체가 다수 사용된다면 하나의 객체를 공유하여 사용하자.

// static, factory, map을 사용한 방법이 일반적


  1. class Image {
  2.         private String url;
  3.  
  4.         public Image(String url) {
  5.                 this.url = url;
  6.  
  7.                 // 이미지를 URL로 부터 다운로드 한다.
  8.                 try {
  9.                         Thread.sleep(5000);
  10.                 } catch (Exception e) {
  11.                         e.printStackTrace();
  12.                 }
  13.         }
  14.  
  15.         public void draw() {
  16.                 System.out.println("draw image : " + url);
  17.         }
  18. }
  19.  
  20. // Image를 전문으로 생성하는 factory
  21. // Factory : 객체의 생성을 한곳에서 중앙집중적으로 관리
  22. class ImageFactory {
  23.         private static final ImageFactory INSTANCE = new ImageFactory(); //싱글톤
  24.         public static ImageFactory getInstance() {
  25.                 return INSTANCE;
  26.         }
  27.         private ImageFactory(){}
  28.         private Map<String, Image> imageMap = new WeakHashMap<>(); // 메모리가 부족할 때 자동으로 해지한다.
  29.        
  30.         public Image createImageFromUrl(String url) {
  31.                 if(!imageMap.containsKey(url)) {
  32.                         imageMap.put(url, new Image(url));
  33.                 }
  34.                 return imageMap.get(url);
  35.         }
  36. }
  37. public class Ex1 {
  38.         public static void main(String[] args) {
  39.                 ImageFactory imgF = ImageFactory.getInstance();
  40.                
  41.                 Image img = imgF.createImageFromUrl("http://a.b.net/1");
  42.                 img.draw();
  43.  
  44.                 Image img2 = imgF.createImageFromUrl("http://a.b.net/2");
  45.                 img2.draw();
  46.  
  47.                 Image img3 = imgF.createImageFromUrl("http://a.b.net/1"); // 같은 url은 캐시
  48.                 img3.draw();
  49.         }
  50.  
  51. }


'java > design_pattern' 카테고리의 다른 글

ObserverPattern - 관찰자 패턴  (0) 2014.07.01
Factory method pattern  (0) 2014.06.27
Prototype Pattern  (0) 2014.06.27
State Pattern  (0) 2014.06.27
Decorator Pattern  (0) 2014.06.27

방어 복사에서 활용


  1. class Period {
  2.         private final Date start;
  3.         private final Date end;
  4.         private static final Integer[] VALUES = { 123456 };
  5.         public static final Collection<Integer> C_VALUES = Collections.unmodifiableCollection(Arrays.asList(VALUES));
  6.         // 생성자에 방어복사를 (Defensive Copy)를 적용해야 한다.
  7.         // 인자의 유효성을 검사하기 전에 먼저 복사하고 나서 원본이 아닌 복사본의 유효성을 검사한다.
  8.         // -> 멀티쓰레드를 고려함.
  9.         public Period(Date start, Date end) {
  10.                 this.start = new Date(start.getTime());
  11.                 this.end = new Date(end.getTime());
  12.  
  13.                 if (this.start.compareTo(this.end) > 0) {
  14.                         throw new IllegalArgumentException(start + " after " + end);
  15.                 }
  16.         }
  17.  
  18.         // 접근자에도 방어복사가 적용되야한다.
  19.         public Date getStart() { // date.getStart().setYear(100);
  20.                 return (Date) start.clone();
  21.         }
  22.  
  23.         public Date getEnd() {
  24.                 return (Date) end.clone();
  25.         }
  26.  
  27.         @Override
  28.         public String toString() {
  29.                 return "Period [start=" + start + ", end=" + end + "]";
  30.         }
  31.  
  32. }
  33.  
  34. public class Ex2 {
  35.         public static void main(String... args) {
  36.                 Date start = new Date();
  37.                 Date end = new Date();
  38.                 Period p = new Period(start, end);
  39.                 System.out.println(p);
  40.                 // end.setYear(12); //setEnd()는 존재하지 않지만 date에 대한 setMethod로 깰수있다.
  41.                 System.out.println(p);
  42.                
  43. //              for (int i = 0; i < Period.VALUES.length; i++) {
  44. ////                    Period.VALUES[i] = 1; // final이 깨진다.
  45. //                      System.out.print(Period.VALUES[i]);
  46. //              }
  47.                 for (int val : Period.C_VALUES) {
  48.                         System.out.print(val);
  49.                 }
  50.         }
  51. }


'java > design_pattern' 카테고리의 다른 글

Factory method pattern  (0) 2014.06.27
Flyweight Pattern  (0) 2014.06.27
State Pattern  (0) 2014.06.27
Decorator Pattern  (0) 2014.06.27
Composite Pattern  (0) 2014.06.27

// State Pattern

// 객체의 상태가 바뀔때마다 행위가 바뀌게 되는 객체들을 '조직화' 하는 디자인 기법


  1. // Item의 상태에 따라 캐릭터의 동작을 변경
  2. // 캐릭터의 동작을 정의한 인터페이스 생성
  3. interface IState {
  4.         public void run();
  5.         public void attack();
  6. }
  7.  
  8. class NormalState implements IState {
  9.  
  10.         @Override
  11.         public void run() {
  12.                 System.out.println("run");
  13.         }
  14.  
  15.         @Override
  16.         public void attack() {
  17.                 System.out.println("attack");
  18.         }
  19.        
  20. }
  21. class FastState implements IState {
  22.  
  23.         @Override
  24.         public void run() {
  25.                 System.out.println("fast run");
  26.         }
  27.  
  28.         @Override
  29.         public void attack() {
  30.                 System.out.println("fast attack");
  31.         }
  32.        
  33. }
  34. class SlowState implements IState {
  35.  
  36.         @Override
  37.         public void run() {
  38.                 System.out.println("slow run");
  39.         }
  40.  
  41.         @Override
  42.         public void attack() {
  43.                 System.out.println("slow attack");
  44.         }
  45.        
  46. }
  47. class Character {
  48.         private int gold;
  49.         private IState state;
  50.        
  51.         public Character(NormalState normalState) {
  52.                 state = normalState;
  53.         }
  54.  
  55.         public void setState(IState state) {
  56.                 this.state = state;
  57.         }
  58.        
  59.         // Replace type code with Polymorphism
  60.         // 상속을 통한 오버라이딩
  61.         public void run() {
  62.                 state.run();
  63.         }
  64.         public void attack() {
  65.                 state.attack();
  66.         }
  67.         public void useGold(int i) {
  68.                 gold -= i;
  69.                 System.out.println("put " + i + " / " + gold);
  70.         }
  71.         public void addGold(int i) {
  72.                 gold += i;
  73.                 System.out.println("get " + i + " / " + gold);
  74.         }
  75. }
  76.  
  77. public class Ex3 {
  78.         public static void main(String...args) {
  79.                 Character c = new Character(new NormalState());
  80.                
  81.                 IState f = new FastState();
  82.                 IState s = new SlowState();
  83.                
  84.                 c.run();
  85.                
  86.                 // item
  87.                 c.setState(f);
  88.                 c.run();
  89.                 c.addGold(100);
  90.                
  91.                 c.setState(s);
  92.                 c.run();
  93.                
  94.         }
  95. }


'java > design_pattern' 카테고리의 다른 글

Flyweight Pattern  (0) 2014.06.27
Prototype Pattern  (0) 2014.06.27
Decorator Pattern  (0) 2014.06.27
Composite Pattern  (0) 2014.06.27
Strategy Pattern  (0) 2014.06.27

// Java Class Library Decorator Pattern. 

// - 1. I/O -- InputStream, OutputStream

// -- 압축되어있는 ByteStream

// -- 1) Byte를 읽는다.

// -- 2) Buffering을 사용한다.

// -- 3) Byte stream 의 압축을 푼다.

// -> GZipInputStream

// 장점

// 1. 추후에 다른 기능을 유연하게 추가 가능 (OCP : 개방 폐쇄의 법칙)

// -- Decorator는 단 하나의 문제만을 해결하기 위해 설계되었다. (SRP : 단일 책임의 법칙)

// 2. 복잡한 문제를 단순한 조각으로 나누어 해결 (Divide and Conquer 분할정복)

// -- 설계 지향적 관점

// -- extends / implements

// -- 구현 상속 / 기능 상속

// -- 클래스 상속 / 인터페이스 상속

// -- 대부분의 상속의 문제는 구현상속을 통해서 발생한다.

// --- 구현상속은 구현이 편리한 대신 위험하다.

// --- 인터페이스 상속은 구현이 힘든 대신 안전하다.

// --- 구현상속은 행위를 변화시킬 때 많은 복잡성이 추가된다.

// --- ex. 컬렉션에 쓰레드 안정성 추가 ? 불변 클래스(immutable class) 만들어야 한다면?

// --- 구체 클래스의 갯수가 2배씩 늘어나게 된다.

// --- 상속 대신 합성을 통해 클래스 계층 구조를 감소 시킨다.


// [ 깨지기 쉬운 기반 클래스 문제 ]

// 구현 상속을 사용하면 기반 클래스의 내부구현이 수정될 때 마다 파생 클래스들이 제대로 동작하는지 확인해야함.

// -> 인터페이스 상속을 통해 해결해야 한다.



  1. public class Ex3 {
  2.  
  3.         public static void main(String[] args) {
  4.                 InputStream in;
  5.                 try {
  6.                         in = new FileInputStream("file");
  7.                         in = new BufferedInputStream(in);
  8.                         in = new ZipInputStream(in);
  9.                 } catch (Exception e) {
  10.                         e.printStackTrace();
  11.                 }
  12.                
  13.                 List<String> list = new ArrayList<>();
  14.                 list = Collections.synchronizedList(list); // Decorator 방식
  15.                 list = Collections.unmodifiableList(list);
  16.         }
  17.  
  18. }


'java > design_pattern' 카테고리의 다른 글

Prototype Pattern  (0) 2014.06.27
State Pattern  (0) 2014.06.27
Composite Pattern  (0) 2014.06.27
Strategy Pattern  (0) 2014.06.27
Template Method Pattern  (0) 2014.06.27

// Composite Pattern - 객체의 포함 관계를 만드는 패턴

// Menu Item : 개별객체

// Popup Menu : 복합객체

// 복합객체 - 개별객체+복합객체 (동일부모 필요)

// command - 부모에 존재해야만 한다.

// 재귀적인 포함을 사용한 복합 객체의 구현을 하는 설계 방법


  1. abstract class BaseMenu {
  2.         private String title;
  3.  
  4.         public BaseMenu(String s) {
  5.                 title = s;
  6.         }
  7.  
  8.         public String getTitle() {
  9.                 return title;
  10.         }
  11.        
  12.         // 부모 입장에서는 구현해 줄 필요가 없고, 자식이 만들어야 한다면 추상메소드로 설계하자.
  13.         public abstract void command(); //하나라도 abstract가 있으면 abstract 클래스가 되어야한다.
  14. }
  15.  
  16. class PopupMenu extends BaseMenu {
  17.         List<BaseMenu> items = new ArrayList<>();
  18.         private Scanner scan;
  19.         public PopupMenu(String s) {
  20.                 super(s);
  21.                 scan = new Scanner(System.in);
  22.         }
  23.        
  24.         public void addMenu(BaseMenu menu) {
  25.                 items.add(menu);
  26.         }
  27.         @Override
  28.         public void command() {
  29.                 System.out.println();
  30.                 int sz = items.size();
  31.                 while(true) {
  32.                         System.out.println();
  33.                         for (int i = 0; i < sz; i++) {
  34.                                 System.out.println((+ 1) + ". " + items.get(i).getTitle());
  35.                         }
  36.                        
  37.                         System.out.println((sz +1) + ". 상위 메뉴로...");
  38.                         System.out.println("메뉴를 선택하세요 >> ");
  39.                        
  40.                         int cmd = scan.nextInt();
  41.                         if(cmd < 1 || cmd > sz + 1) {
  42.                                 continue;
  43.                         }
  44.                         if(cmd == sz +1) {
  45.                                 break;
  46.                         }
  47.                         items.get(cmd - 1).command();
  48.                 }
  49.         }
  50.        
  51. }
  52.  
  53. class MenuItem extends BaseMenu {
  54.  
  55.         public MenuItem(String s) {
  56.                 super(s);
  57.         }
  58.  
  59.         @Override
  60.         public void command() {
  61.                 System.out.println(getTitle() + "command execution!");
  62.                
  63.         }
  64.  
  65. }
  66.  
  67. public class Ex1 {
  68.  
  69.         public static void main(String[] args) {
  70.                 PopupMenu menubar = new PopupMenu("MenuBar");
  71.                 PopupMenu p1 = new PopupMenu("화면설정");
  72.                 PopupMenu p2 = new PopupMenu("소리설정");
  73.                
  74.                 menubar.addMenu(p1);
  75.                 menubar.addMenu(p2);
  76.                
  77.                 p1.addMenu(new MenuItem("해상도 변경"));
  78.                 p1.addMenu(new MenuItem("색상 변경"));
  79.                 p1.addMenu(new MenuItem("명암 변경"));
  80.                
  81.                 p2.addMenu(new MenuItem("볼륨 조절"));
  82.                 p2.addMenu(new MenuItem("음향 조절"));
  83.                
  84.                 menubar.command();
  85.         }
  86.  
  87. }


'java > design_pattern' 카테고리의 다른 글

State Pattern  (0) 2014.06.27
Decorator Pattern  (0) 2014.06.27
Strategy Pattern  (0) 2014.06.27
Template Method Pattern  (0) 2014.06.27
Adapter 패턴  (0) 2014.06.27

+ Recent posts