객체지향적 사고와 설계를 해야하는 이유는 사용자(관리자)의 서술적인 니즈를 비즈니스에 맞는 모델링을 하기위한 최적의 방법이기 때문이다.


  1. 객체지향 사물의 분류
    1. 사물(Things)은 곧 객체이다.
    2. 사물에는 형태를 가진 것과 개념만 존재하는 것으로 분류할 수 있다.
    3. 소프트웨어 분석 설계 구현을 한다는 것은 실세계의 사물을 가상세계의 사물로 전환 하는 것이다.
    4. 객체 모델링, 데이터 모델링도 다 사물들을 관리하는 기준에 맞춰 분류하는 것이다.
    5. 타입, 클래스는 객체 즉 사물을 분류했을 때 정의하는 것에 지나지 않는다.
  2. 사물을 어떻게 분류할 것인가?
    1. 책을 예시로 보면 책은 객체이다. 책에 대한 정보만 관리하는 것은 개념 객체이고 책의 실물을 관리하는 사물을 관리하는 객체가 구별되어 관리되어야 한다. 
    2. 책이라는 객체가 책 정보에 대한 분류 기준으로 도서문헌상의 분류 규칙을 따르므로 다양한 분류체계를 관리하는 객체도 발생할 수 있다.
    3. 사물은 단순이 존재한다고 하나의 객체만은 아니다.
    4. 보는 관점, 각 비즈니스 도메인별로 차이가 발생하므로 사물의 분류 기준을 비즈니스 에 맞춰 모델링이 되어야 한다.

출처(http://www.slideshare.net/dahlmoon/20160131)

블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.

객체지향 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 : 간단한 언어를 설계하고 언어 해석기를 만들어 사용



블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.

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. }


블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.

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
Bridge Pattern - 브릿지 패턴  (0) 2014.07.01
Memento Pattern - 메멘토 패턴  (0) 2014.07.01
Command Pattern - 명령패턴  (0) 2014.07.01
Proxy Pattern - 대리자 패턴  (0) 2014.07.01
블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.

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
Memento Pattern - 메멘토 패턴  (0) 2014.07.01
Command Pattern - 명령패턴  (0) 2014.07.01
Proxy Pattern - 대리자 패턴  (0) 2014.07.01
Iterator Pattern - 열거자  (0) 2014.07.01
블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.

 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
Command Pattern - 명령패턴  (0) 2014.07.01
Proxy Pattern - 대리자 패턴  (0) 2014.07.01
Iterator Pattern - 열거자  (0) 2014.07.01
Visitor Pattern - 방문자 패턴  (0) 2014.07.01
블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.


 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. }


블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.

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. }



블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.

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. }


블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.

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
Chain of Responsibility Pattern - 책임의 전가  (0) 2014.07.01
MediatorPattern - 중재자 패턴  (0) 2014.07.01
ObserverPattern - 관찰자 패턴  (0) 2014.07.01
Factory method pattern  (0) 2014.06.27
블로그 이미지

기계새

Java, Spring, iBatis, Maven, eclipse 개발관련 잡다한 메모공간입니다.