객체지향 5대 원칙

SOLID

SRP - 단일 책임의 법칙 : 클래스는 단 하나의 책임만을 가져야 한다.

OCP - 개방 폐쇄의 법칙 : 수정에는 닫혀있고 확장에는 열려있어야한다.

LSP - 리스코프의 치환법칙 : 자식은 부모로 대체 가능해야한다.

ISP - 인터페이스 분리의 법칙 : 범용 인터페이스 보다는 세분화된 인터페이스가 낫다.

DIP - 의존 관계역전의 법칙 : 구체 클래스에 의존하지 말고 인터페이스에 의존해라.


디자인 패턴


생성 (5)

Singleton : 하나의 클래스로 어디서든 접근 가능한 객체

Abstract Factory : 추상적인 부품을 통한 추상적 제품의 조립 (팩토리도 인터페이스 기반으로 만들자)

Factory Method : 변하지 않는 것은 부모가, 변하는것(객체생성이라) 자식이 오버라이딩

Builder : 동일한 공정에 다른 표현을 가진 객체 생성

Prototype : 복사본(clone) 을 통한 객체 생성

구조 (7)

Adapter : 인터페이스 변경을 통해 다른 클래스 처럼 보이기

Bridge : 확장 용이성을 위한 계층의 분리

Proxy : 기존 요소를 대신하기 위한 클래스(대리자)

Remote : 원격 객체를 대신

Virtual : 기존 객체의 생성 비용이 클 때

Protection : 기존 객체에 대한 접근 제어.

Facade : 하위 시스템 단순화하는 상위 시스템

Composite : 복합객체를 만들기 위한 패턴

Decorator : Composite와 같은데 기능의 확장

Flyweight : 동일한 속성을 가진 객체는 공유

행위 (11)

Iterator : 열거. 복합객체의 내부구조와 관계없이 동일한 구조로 열거 (Iterable, Iterator<T>)

Visitor : 복합객체 요소의 연산을 수행

Observer : 하나의 사건 발생 시 등록된 여러 객체에 전달

State : 상태에 따른 동작의 변화

Chain of Responsibility : 사건 발생 시 첫번째 객체가 처리 불가 시 다음으로 전달

Mediator : M:N 의 객체관계를 객체와 중재자 간의 1:1 관계로 단순화

Template Method : 변하지 않는것은 부모가, 변하는 것은 자식이 오버라이딩

Strategy : 알고리즘의 변화를 인터페이스기반의 클래스로 분리

Memento : 캡슐화를 위반하지 않고 객체의 상태를 저장 및 복구

Command : 명령의 캡슐화를 통한 Redo/Undo Macro

Interpreter : 간단한 언어를 설계하고 언어 해석기를 만들어 사용



Facade 패턴

 - 코드 랩핑(Code Wrapping)을 통해 의존성을 낮춘다.


  1. class Hotel {
  2.         // 호텔 정보
  3. }
  4.  
  5. class Flight {
  6.         @SuppressWarnings("unchecked")
  7.         public List<Flight> getFlightsFor(Date from, Date to) {
  8.                 return Collections.EMPTY_LIST;
  9.         }
  10. }
  11.  
  12. class HotelBooker {
  13.         @SuppressWarnings("unchecked")
  14.         public List<Hotel> getHotelNamesFor(Date from, Date to) {
  15.                 return Collections.EMPTY_LIST;
  16.         }
  17. }
  18.  
  19. class FlightBooker {
  20.         @SuppressWarnings("unchecked")
  21.         public List<Flight> getFlightNamesFor(Date from, Date to) {
  22.                 return Collections.EMPTY_LIST;
  23.         }
  24. }
  25.  
  26. class TravelFacade { // 코드 랩핑, 사용자는 Hotel, FLight에 대해 알 필요 없다.
  27.         private HotelBooker hotelBooker;
  28.         private FlightBooker flightBooker;
  29.  
  30.         public void getFlightAndHotels(Date from, Date to) {
  31.         }
  32.  
  33.         public HotelBooker getHotelBooker() {
  34.                 return hotelBooker;
  35.         }
  36.  
  37.         public FlightBooker getFlightBooker() {
  38.                 return flightBooker;
  39.         }
  40. }
  41.  
  42. public class Ex1 {
  43.  
  44.         public static void main(String[] args) {
  45.         }
  46.  
  47. }


Bridge Pattern

 - 기능과 구현을 분리하는 패턴. 

 - 기능과 구현을 별도의 클래스로 정의하여 서로 분리하는 방법

 1. 계층 구조를 완만하게 만드는 효과

 2. 구현을 사용자로부터 완벽하게 숨김

 상속을 완만하게 만든다.


  1. interface IMp3 {
  2.         void play();
  3.  
  4.         void stop();
  5. }
  6.  
  7. class IPod implements IMp3 {
  8.  
  9.         @Override
  10.         public void play() {
  11.                 System.out.println("play ipod");
  12.         }
  13.  
  14.         @Override
  15.         public void stop() {
  16.                 System.out.println("stop ipod");
  17.  
  18.         }
  19.  
  20. }
  21.  
  22. // 사용자가 imp3 를 직접 사용하게 하지말고 중간층을 도입.
  23. // 내부적으로 imp3를 사용.
  24. // 내부의 구현을 사용자로부터 완벽하게 숨긴다.
  25. // 기능과 구현을 구분한다.
  26. class Mp3 {
  27.         IMp3 mp3;
  28.  
  29.         public Mp3(IMp3 mp3) {
  30.                 this.mp3 = mp3;
  31.         }
  32.  
  33.         void play() {
  34.                 mp3.play();
  35.         }
  36.  
  37.         void stop() {
  38.                 mp3.stop();
  39.         }
  40.  
  41.         // 1분간 플레이 요구사항 발생
  42.         public void playOneMinute() {
  43.                 // 1분
  44.                 mp3.play();
  45.         }
  46. }
  47.  
  48. class People {
  49.         public void useMp3(Mp3 mp3) {
  50.                 mp3.play();
  51.         }
  52.  
  53. }
  54.  
  55. public class Ex1 {
  56.         public static void main(String... args) {
  57.                 People p = new People();
  58.                 Mp3 mp3 = new Mp3(new IPod());
  59.                 p.useMp3(mp3);
  60.         }
  61.  
  62. }


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

Java Design Pattern 총 정리  (0) 2014.07.01
Facade Pattern - 퍼사드 패턴  (0) 2014.07.01
Memento Pattern - 메멘토 패턴  (0) 2014.07.01
Command Pattern - 명령패턴  (0) 2014.07.01
Proxy Pattern - 대리자 패턴  (0) 2014.07.01

Memento Pattern 

 - 객체의 상태 저장을 위한 패턴

 - 클래스 내부에 인스턴스 내부의 상태를 나타내는 역할을 도입해서 캡슐화의 파괴에 빠지지 않고  저장과 복원을 실행하는 패턴

 - 커맨드 패턴과 비슷하니 잘 분리를 해서 사용해야함.

Ex. 직렬화 (Serialization), Date, snap shot. 자바 내부에서 거의 쓰이지 않는다.


  1. class Machine {
  2.         private int state1;
  3.         private int state2;
  4.  
  5.         private class Memento {
  6.                 int state1;
  7.                 int state2;
  8.         }
  9.  
  10.         private List<Memento> backup = new ArrayList<>();
  11.  
  12.         public int createMemento() {
  13.                 Memento m = new Memento();
  14.                 m.state1 = this.state1;
  15.                 m.state2 = this.state2;
  16.                 backup.add(m);
  17.  
  18.                 return backup.size() - 1; // 특정 토큰을 반환한다.
  19.         }
  20.        
  21.         void restoreState(int token) {
  22.                 Memento m = backup.get(token); // 저장된 토큰으로 복구한다.
  23.                 this.state1 = m.state1;
  24.                 this.state2 = m.state2;
  25.                
  26. //              backup.remove(token); // 복구 시 삭제하는 것은 정책으로 결정.
  27.                
  28.         }
  29.         void setState(int a, int b) {
  30.                 this.state1 = a;
  31.                 this.state2 = b;
  32.         }
  33.  
  34.         @Override
  35.         public String toString() {
  36.                 return "Machine [state1=" + state1 + ", state2=" + state2 + ", backup="
  37.                                 + backup + "]";
  38.         }
  39.        
  40. }
  41.  
  42. public class Ex2 {
  43.  
  44.         public static void main(String[] args) {
  45.                 Machine m = new Machine();
  46.                 m.setState(12);
  47.                 System.out.println(m.toString());
  48.                 int token = m.createMemento();
  49.                
  50.                 m.setState(3040); // 중간에 상태가 바뀌어도
  51.                 System.out.println(m.toString());
  52.                 m.restoreState(token); // 기억된 토큰으로 복구 시킬 수 있다.
  53.                 System.out.println(m.toString());
  54.                
  55.         }
  56.  
  57. }


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

Facade Pattern - 퍼사드 패턴  (0) 2014.07.01
Bridge Pattern - 브릿지 패턴  (0) 2014.07.01
Command Pattern - 명령패턴  (0) 2014.07.01
Proxy Pattern - 대리자 패턴  (0) 2014.07.01
Iterator Pattern - 열거자  (0) 2014.07.01

 Command Pattern

 - 명령들을 캡슐화(클래스)

 -  명령을 수행 단위로 묶음

 -> 명령을 추상화


  특정 객체에 대한 특정 작업을 캡슐화 하여 요청을 하는 객체와 수행하는 객체를 분리한다.


 요청을 객체화 형태로 캡슐화 하면 요청에 대한 저장 및 로깅, 연산의 취소를 지원할 수 있다.


  1. interface Shape {
  2.         void draw(); // LSP(리스코프의 치환 법칙) : 자식은 부모로 대체 가능해야 한다.
  3. }
  4.  
  5. class Rect implements Shape {
  6.         @Override
  7.         public void draw() {
  8.                 System.out.println("Draw Rect");
  9.         }
  10. }
  11.  
  12. class Circle implements Shape {
  13.         @Override
  14.         public void draw() {
  15.                 System.out.println("Draw Circle");
  16.         }
  17. }
  18.  
  19. interface ICommand {
  20.         void execute();
  21.  
  22.         boolean canUndo();
  23.  
  24.         void undo();
  25. }
  26.  
  27. abstract class AddCommand implements ICommand {
  28.         private final List<Shape> shapes;
  29.  
  30.         public AddCommand(List<Shape> s) {
  31.                 this.shapes = s;
  32.         }
  33.  
  34.         @Override
  35.         public void execute() {
  36.                 shapes.add(createShape());
  37.         }
  38.  
  39.         @Override
  40.         public boolean canUndo() {
  41.                 return true;
  42.         }
  43.  
  44.         @Override
  45.         public void undo() {
  46.                 shapes.remove(shapes.size() - 1);
  47.         }
  48.  
  49.         public abstract Shape createShape();
  50. }
  51.  
  52. class AddRectCommand extends AddCommand {
  53.         public AddRectCommand(List<Shape> s) {
  54.                 super(s);
  55.         }
  56.  
  57.         @Override
  58.         public Shape createShape() {
  59.                 return new Rect();
  60.         }
  61. }
  62.  
  63. class AddCircleCommand extends AddCommand {
  64.         public AddCircleCommand(List<Shape> s) {
  65.                 super(s);
  66.         }
  67.  
  68.         @Override
  69.         public Shape createShape() {
  70.                 return new Circle();
  71.         }
  72. }
  73.  
  74. class DrawCommand implements ICommand {
  75.         private final List<Shape> shapes;
  76.  
  77.         public DrawCommand(List<Shape> s) {
  78.                 shapes = s;
  79.         }
  80.  
  81.         @Override
  82.         public void execute() {
  83.                 for (Shape e : shapes) {
  84.                         e.draw();
  85.                 }
  86.         }
  87.  
  88.         @Override
  89.         public boolean canUndo() {
  90.                 return true;
  91.         }
  92.  
  93.         @Override
  94.         public void undo() {
  95.                 System.out.println("Screen Cleared!!!");
  96.         }
  97. }
  98.  
  99. class MacroCommand implements ICommand {
  100.         // Composite Pattern
  101.         private List<ICommand> commands = new ArrayList<>();
  102.  
  103.         public void addCommand(ICommand c) {
  104.                 commands.add(c);
  105.         }
  106.  
  107.         // Ctrl + C  / Ctrl + D
  108.         // Ctrl + D
  109.        
  110.         @Override
  111.         public void execute() {
  112.                 for (ICommand e : commands) {
  113.                         e.execute();
  114.                 }
  115.         }
  116.  
  117.         @Override
  118.         public boolean canUndo() {
  119.                 for (int i = 0; i < commands.size(); i++) {
  120.                         if (commands.get(i).canUndo() == false)
  121.                                 return false;
  122.                 }
  123.  
  124.                 return true;
  125.         }
  126.  
  127.         @Override
  128.         public void undo() {
  129.                 int n = commands.size() - 1;
  130.                 while (>= 0) {
  131.                         commands.get(n).undo();
  132.                         n--;
  133.                 }
  134.         }
  135.  
  136. }
  137.  
  138. public class Ex1 {
  139.         private static Scanner scanner;
  140.  
  141.         public static void main(String[] args) {
  142.                 scanner = new Scanner(System.in);
  143.                 List<Shape> shapes = new ArrayList<>();
  144.  
  145.                 Stack<ICommand> commandStack = new Stack<>();
  146.                 Stack<ICommand> redoStack = new Stack<>();
  147.                
  148.                 MacroCommand mc = new MacroCommand();
  149.                 mc.addCommand(new AddRectCommand(shapes));
  150.                 mc.addCommand(new AddCircleCommand(shapes));
  151.                 mc.addCommand(new DrawCommand(shapes));
  152.                 mc.execute();
  153.                
  154.                 commandStack.add(mc);
  155.  
  156.                 ICommand command = null;
  157.                 while (true) {
  158.                         System.out.print("choice : ");
  159.                         int cmd = scanner.nextInt();
  160.  
  161.                         switch (cmd) {
  162.                         case 1:
  163.                                 command = new AddRectCommand(shapes);
  164.                                 command.execute();
  165.                                 commandStack.push(command);
  166.                                 break;
  167.  
  168.                         case 2:
  169.                                 command = new AddCircleCommand(shapes);
  170.                                 command.execute();
  171.                                 commandStack.push(command);
  172.                                 break;
  173.  
  174.                         case 9:
  175.                                 command = new DrawCommand(shapes);
  176.                                 command.execute();
  177.                                 commandStack.push(command);
  178.                                 break;
  179.  
  180.                         case -1:
  181.                                 command = redoStack.pop();
  182.                                 command.execute();
  183.  
  184.                         case 0:
  185.                                 // Undo(ctrl + z)
  186.                                 command = commandStack.pop();
  187.  
  188.                                 if (command.canUndo()) {
  189.                                         command.undo();
  190.                                         redoStack.add(command);
  191.                                 }
  192.                                 break;
  193.                         }
  194.  
  195.                 }
  196.         }
  197. }


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

Bridge Pattern - 브릿지 패턴  (0) 2014.07.01
Memento Pattern - 메멘토 패턴  (0) 2014.07.01
Proxy Pattern - 대리자 패턴  (0) 2014.07.01
Iterator Pattern - 열거자  (0) 2014.07.01
Visitor Pattern - 방문자 패턴  (0) 2014.07.01


 Proxy Pattern (대리자 패턴)

 -- 처리과정이 복잡하거나 시스템의 리소스를 많이 필요하거나 하는 객체가 필요할 때,

 -- 간단한 처리는 대리자가 하고 실제객체가 필요할 때 생성하여 처리하는 패턴.


 1. Remote Proxy : 원격 객체에 대한 로컬의 대리자

  : RMI(Remote Method Invoke)

: C# WCF(SOAP), Android(Proxy), COM(RPC)

 2. Virtual Proxy : 많은 비용이 요구되는 객체를 생성하는 경우 실제 객체가 사용되기 전 까지 

  해당하는 객체에 대한 로딩을 지연할 수 있다.

Flyweight Pattern과 함께 사용한다. (Cache)

 3. Protection Proxy : 보호가 요구되는 객체에 대한 접근을 통제하고, 대리자를 통해 접근 제어하는 방법

객체의 타입에 따른 접근 제어 (ex. 리플렉션)


  1. package com.tistory.metalbird;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. class Calc {
  7.         public void plus() {
  8.  
  9.         }
  10. }
  11.  
  12. class CalcProxy {
  13.         public void plus() {
  14.                 new Calc().plus(); // RMI 기술의 예. 중간객체를 둠으로써 문제를 해결
  15.         }
  16. }
  17.  
  18. // 인터페이스 기반의 설계
  19. interface Image {
  20.         void showImage();
  21. }
  22.  
  23. class ImageProxy implements Image {
  24.         private String url;
  25.        
  26.         public ImageProxy(String url) {
  27.                 this.url = url;
  28.         }
  29.         @Override
  30.         public void showImage() {
  31.                 // show image 가 호출 되었을때 로딩을 한다.
  32.                 // 부하가 많이 걸리는 작업을 대리자에게 넘긴다.
  33.                 System.out.println("lazy load");
  34.                 RealImage image = new RealImage(url);
  35.                 image.showImage();
  36.         }
  37.  
  38. }
  39.  
  40. // 라이브러리 형태로 존재
  41. class RealImage implements Image {
  42.         private String url;
  43.  
  44.         public RealImage(String url) {
  45.                 this.url = url;
  46.                 // downloading from url.
  47.                 // 부하가 많이 걸린다.
  48.         }
  49.  
  50.         public void showImage() {
  51.                 System.out.println("ShowImage : " + url);
  52.         }
  53.  
  54. }
  55.  
  56. public class Ex1 {
  57.  
  58.         public static void main(String[] args) {
  59.                 List<Image> images = new ArrayList<>();
  60.                 images.add(new ImageProxy("http://a.net/1.jpg"));
  61.                 images.add(new ImageProxy("http://a.net/2.jpg"));
  62.                 images.add(new ImageProxy("http://a.net/3.jpg"));
  63.                 images.add(new ImageProxy("http://a.net/4.jpg"));
  64.  
  65.                 for (Image i : images) {
  66.                         i.showImage();
  67.                 }
  68.         }
  69.  
  70. }


Iterator Pattern 

- 컬렉션의 내부구조와 상관없이 그 집합체 안의 모든 항목을 열거하는 패턴

 - Java에서는 Iterable<E> / Iterator<E> 라는 인터페이스를 구현하면 사용 가능하다.


  1. class Node<E> { //Generiec - type argument
  2.         public final E data;
  3.         public final Node<E> next; // Object
  4.        
  5.         public Node(E data, Node<E> next) { // Object
  6.                 this.data = data;
  7.                 this.next = next;
  8.         }
  9.        
  10. }
  11.  
  12. class SList<E> implements Iterable<E> {
  13.         private Node<E> head;
  14.        
  15.        
  16.         public SList() {
  17.                 head = null;
  18.         }
  19.         public void addFront (E n) {
  20.                 head = new Node<E>(n, head);
  21.         }
  22.         public E front() {
  23.                 return head.data;
  24.         }
  25.        
  26.         @Override
  27.         public Iterator<E> iterator() {
  28.                 return new SListIterator<E>(head);
  29.         }
  30.        
  31.         // 외부로 노출되지 않기 위해 private class 로 구현하는게 일반적이다.
  32.         @SuppressWarnings("hiding")
  33.         private class SListIterator<E> implements Iterator<E> {
  34.                 private Node<E> current;
  35.                
  36.                 public SListIterator(Node<E> node) {
  37.                         this.current = node;
  38.                 }
  39.                
  40.                 @Override
  41.                 public boolean hasNext() {
  42.                         return current != null;
  43.                 }
  44.  
  45.                 //현재의 요소를 반환하며 다음으로 이동
  46.                 @Override
  47.                 public E next() {
  48.                         E value = current.data;
  49.                         current = current.next;
  50.                         return value;
  51.                 }
  52.  
  53.                 @Override
  54.                 public void remove() {
  55.                         // 지원하지 않음
  56.                         throw new UnsupportedOperationException("remove() unsupported!");
  57.                        
  58.                 }
  59.                
  60.         }
  61. }
  62. public class Ex2 {
  63.        
  64.         public static void main(String[] args) {
  65.                 SList<String> s = new SList<>();
  66.                 s.addFront("aaa");
  67.                 s.addFront("bbb");
  68.                 s.addFront("ccc");
  69.                 Iterator<String> iter = s.iterator();
  70.                
  71.                 while(iter.hasNext()) {
  72.                         System.out.println(iter.next());
  73.                 }
  74.                
  75.                 for(String e : s) { // 내부적으로 iterator 를 사용한다.
  76.                         System.out.println(e);
  77.                 }
  78.                
  79.                 //Collections, List<T>  // interface
  80.                
  81.         }
  82.  
  83. }



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

+ Recent posts