Method Reference

 - 타입만 맞춰주면 내부적으로 연결된다.

인터페이스의 데이터 타입이 맞으면 동작을 보장.

ex)

btn.setListener(dialog::doOnClick); //  Method Reference - 타입만 맞춰주면 내부적으로 연결한다.

btn.setListener(System.out::println); 

Stream<Button1> stream = Arrays.stream(labels).map(Button1::new); // Construct Reference



  1. @FunctionalInterface
  2. interface IClickListener {
  3.         void onClick(String s);
  4. }
  5. class Button1 {
  6.         private List<IClickListener> listeners = new ArrayList<>();
  7.        
  8.         private String text;
  9.        
  10.         public Button1 (){}
  11.         public Button1(String s) {
  12.                 text = s;
  13.                 System.out.println(text);
  14.         }
  15.         public void setListener(IClickListener listener) {
  16.                 this.listeners.add(listener);
  17.         }
  18.         public void onClick() {
  19. //              for(IClickListener l : listeners) {
  20. //                      l.onClick("click");
  21. //              }
  22.                 listeners.forEach(System.out::println); // 동일 동작
  23.         }
  24. }
  25. class Dialog {
  26.         public void doOnClick(String text) {
  27.                 System.out.println(text);
  28.         }
  29. }
  30. @FunctionalInterface // 단일추상메소드 인터페이스임을 알림
  31. // 컴파일러가 메소드가 하나만 존재해야 한다는 것을 보장.
  32. interface IFoo { // 단일 인터페이스
  33.         void foo(String s, String s1);
  34. //      void goo(); // 두개는 선언 못한다.
  35.        
  36. }
  37.  
  38. @FunctionalInterface
  39. interface IGoo {
  40.         void goo();
  41. }
  42. public class Ex2 {
  43.         public static void goo(String s ) {
  44.                 System.out.println("goo" + s);
  45.         }
  46.         public static void main(String[] args) {
  47.                 IFoo foo = (s, s1) -> System.out.println(+ s1);
  48. //              IFoo foo = s -> System.out.println(s); // 인자가 하나인 경우 괄호가 생략 가능하다.
  49.                 foo.foo("d""c");
  50.                
  51.                 Button1 btn = new Button1();
  52.                 // 메소드 레퍼런스
  53.                 // 메소드를 맵핑 시킨다.
  54.                
  55.                 Dialog dialog = new Dialog();
  56.                 btn.setListener(dialog::doOnClick); // 타입만 맞춰주면 내부적으로 연결한다.
  57.                 btn.setListener(System.out::println);
  58.                
  59.                 btn.setListener(Ex2::goo);
  60.                
  61.                 btn.onClick();
  62.                
  63.                
  64.                 String[] labels = {"AAA","BBB","CCC"};
  65.                
  66.                 Stream<Button1> stream = Arrays.stream(labels).map(Button1::new); // Construct Reference
  67.                 stream.forEach(Button1::onClick);
  68.         }
  69. }


'java' 카테고리의 다른 글

Java 8 신기능 정리 - Stream  (0) 2014.07.02
Java 8 신기능 정리 - Default Method  (0) 2014.07.02
Java 8 신기능 정리 - Lambda Expression  (0) 2014.07.01
Java7 의 신기능 정리  (0) 2014.07.01
Java 7 try catch 문법. autocloseable  (0) 2014.06.20

Java 8 2014/03/18 Released

 언어의 형태가 바뀌었다.

 순수객체지향 지향 -> Functional Programming. 

 병렬 지원 - 라이브러리, 언어 차원에서 지원

 C# 4(2009)에서 지원, C++ 11(2011)에서 지원 (Visual studio 2010, gcc 4.6,4.8)


람다 표현식

 - 실행할 함수구문의 블럭을 보낸다.

 - 마지막 표현식이 리턴 값이 된다.

 - 중괄호 사용 시 리턴을 표기해줘야 한다.

 - 선언과 동시에 구현한다. 


  1. class Worker implements Runnable {
  2.  
  3.         @Override
  4.         public void run() {
  5.                 System.out.println("Hello Thread.");
  6.         }
  7.  
  8. }
  9.  
  10. class LengthComparator implements Comparator<String> {
  11.  
  12.         @Override
  13.         public int compare(String o1, String o2) {
  14.                 return Integer.compare(o1.length(), o2.length());
  15.         }
  16.  
  17. }
  18.  
  19. public class Ex1 {
  20.  
  21.         public static void main(String[] args) {
  22.                 // old 1
  23.                 new Thread(new Worker()).start();
  24.                 // old 2
  25.                 new Thread(new Runnable() { // assistance 가 지원된다.
  26.  
  27.                                         @Override
  28.                                         public void run() {
  29.                                                 // blah blah
  30.                                                 System.out.println("old_2");
  31.                                         }
  32.                                 }).run();
  33.  
  34.                 // new
  35.                 new Thread(() -> System.out.println("Hello") // 실행할 함수 구문의 블럭을 보낸다.
  36.                 // 인터페이스의 형태로 보낸다. functional interface
  37.                 ).start();
  38.                
  39.                 int oldCom = new LengthComparator().compare("f""s");
  40.                 Comparator<String> lengthComparator = (String first, String second) -> Integer
  41.                                 .compare(first.length(), second.length()); // 마지막 표현식이 리턴 값이 된다.
  42.                 Comparator<String> lenCom = (first, second) -> {
  43.                         return Integer.compare(first.length(), second.length()); //중괄호 사용시 리턴을 줘야한다.
  44.                 };
  45.                 System.out.println(oldCom);
  46.                 lengthComparator.compare("com""com");
  47.                 lenCom.compare("com""com2");
  48.                
  49.                 Button button = new Button();
  50.                 button.setButtonListener(()->System.out.println("click")); // 선언하며 구현한다.
  51.                 button.setButtonListener(new IButtonListener() {
  52.                        
  53.                         @Override
  54.                         public void onClick() {
  55.                                 System.out.println("old_click");
  56.                         }
  57.                 });
  58.                 // 옵저버 패턴의 구현 형식이 바뀌게 된다.
  59.                 button.click();
  60.         }
  61. }
  62. interface IButtonListener {
  63.         void onClick();
  64. }
  65. class Button {
  66.         IButtonListener listener;
  67.         void setButtonListener (IButtonListener listener) {
  68.                 this.listener = listener;
  69.         }
  70.         void click() {
  71.                 if(listener != null) {
  72.                         listener.onClick();
  73.                 }
  74.         }
  75. }
  76.  
  77. class Dialog implements IButtonListener {
  78.  
  79.         @Override
  80.         public void onClick() {
  81.                 System.out.println("click");
  82.         }
  83.        
  84. }


Java7의 달라진점은 크게 5가지로 정리할수 있다.


 1) Java String Switch

 2) 이진 표현과 _ 추가

 3) Multi-Exception Catch 향상된 예외처리

 4) Diamond Operator 

 5) Auto Closable 향상된 자원관리


  1. public class Ex1 {
  2.         public static void main(String... args) {
  3.                 // 1)
  4.                 int n = 10;
  5.                 switch (n) { // 이전 - int, enum 만 사용 가능
  6.                 case 1:
  7.                 case 2:
  8.                 }
  9.                 String s = "안녕";
  10.                 switch (s) { // java7 이후. String 도 사용 가능.
  11.                 case "안녕":
  12.                 case "hello":
  13.                 }
  14.  
  15.                 // 2)
  16.                 long old_l = 100000; // 실생활 1,000,000
  17.                 long new_l = 1_000_000; // 컴파일러에 의해 무시되지만 가독성이 증가
  18.                 int b_n = 0b1, b_2 = 0b10, b_3 = 0b1111_1010_1111; // 2진수 표현
  19.                
  20.                
  21.                 // 3)
  22.                 try {
  23.                         foo(n);
  24.                 } catch (ExceptionOne | ExceptionTwo | ExceptionThree e) { // 동일한 예외는 묶어서 관리한다.
  25.                         e.printStackTrace();
  26.                 }
  27.                
  28.                 // 4)
  29.                 List<Long> list = new ArrayList<>();
  30.                 list.add(old_l);
  31.                 list.add(new_l);
  32.                 list.add((long) b_n);
  33.                 list.add((long) b_2);
  34.                 list.add((long) b_3);
  35. //              list.addAll(Arrays.asList(old_l,new_l,b_n,b_2,b_3));
  36.                
  37.                 // 5)
  38.                 try(FileOutputStream fos = new FileOutputStream("test.txt"); // AutoClosable C# 에서 사용되는 기능
  39.                                 DataOutputStream dos = new DataOutputStream(fos)) {
  40.                         dos.writeUTF("xxx");
  41.                        
  42.                 } catch (IOException e) {
  43.                        
  44.                 } catch (Exception e) {
  45.                        
  46.                 }
  47.                
  48.                
  49.                
  50.  
  51.         }
  52.  
  53.         static void foo(int n) throws ExceptionOne, ExceptionTwo, ExceptionThree {
  54.                 if (== 0)
  55.                         throw new ExceptionOne();
  56.                 if (== 1)
  57.                         throw new ExceptionTwo();
  58.                 if (== 2)
  59.                         throw new ExceptionThree();
  60.  
  61.         }
  62. }
  63.  
  64. class ExceptionOne extends Exception {
  65.         private static final long serialVersionUID = -5677634028059042523L;
  66.  
  67. }
  68.  
  69. class ExceptionTwo extends Exception {
  70.         private static final long serialVersionUID = -6269740256108905025L;
  71.  
  72. }
  73.  
  74. class ExceptionThree extends Exception {
  75.         private static final long serialVersionUID = -8353059137079175265L;
  76. }


'java' 카테고리의 다른 글

Java 8 신기능 정리 - Method Reference, Construct Reference  (0) 2014.07.02
Java 8 신기능 정리 - Lambda Expression  (0) 2014.07.01
Java 7 try catch 문법. autocloseable  (0) 2014.06.20
코드 품질 관리  (0) 2014.04.17
Java Apn 샘플코드  (0) 2014.04.14

객체지향 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. }



+ Recent posts