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

// 패턴 적용

// 2. 변하는 것을 '클래스화' 하자.

// -- Strategy pattern (전략패턴)

// 2.1 인터페이스를 설계하자.


  1. interface IValidator {
  2.         boolean validate(char c);
  3. }
  4. class DigitOnlyValidator implements IValidator {
  5.  
  6.         @Override
  7.         public boolean validate(char c) {
  8.                 return Character.isDigit(c);
  9.         }
  10. }
  11. class AllPassValidator implements IValidator {
  12.  
  13.         @Override
  14.         public boolean validate(char c) {
  15.                 return true;
  16.         }
  17.        
  18. }
  19. class LineEdit2 {
  20.         private JFrame frame;
  21.         private StringBuilder builder = new StringBuilder();
  22.         private IValidator iValidator;
  23.        
  24.         public void setValidator(IValidator iv) {
  25.                 iValidator = iv;
  26.         }
  27.         public LineEdit2() {
  28.                 frame = new JFrame();
  29.                 frame.setSize(300200);
  30.                 frame.setTitle("EditBox");
  31.                 iValidator = new AllPassValidator(); //default
  32.                
  33.                 Container cp = frame.getContentPane();
  34.                 cp.setLayout(new FlowLayout());
  35.                
  36.                 final JLabel label = new JLabel("");
  37.                 cp.add(label);
  38.                
  39.                 frame.addKeyListener(new KeyListener() { //inner class
  40.                        
  41.                         @Override
  42.                         public void keyTyped(KeyEvent e) { //키를 입력했다. (Press + Release)
  43.                                 char c = e.getKeyChar();
  44.                                 System.out.println(c);
  45.                                 if(== '\n') {
  46.                                         builder = new StringBuilder();
  47.                                         label.setText("");
  48.                                 }
  49.                                 if(iValidator.validate(c)) {
  50.                                         builder.append(c);
  51.                                         label.setText(builder.toString());
  52.                                 }
  53.                         }
  54.                         @Override
  55.                         public void keyReleased(KeyEvent e) {} // 키를 뗐다.
  56.                         @Override
  57.                         public void keyPressed(KeyEvent e) {} // 키를 눌렀다.
  58.                 });
  59.                 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 프로세스 종료시
  60.                
  61.         }
  62.         public boolean validate(char c) {
  63.                 return Character.isDigit(c);
  64.         }
  65.  
  66.         public void show() {
  67.                 frame.setVisible(true);
  68.  
  69.         }
  70. }
  71. public class Ex2 {
  72.        
  73.         public static void main(String...args) {       
  74.                 LineEdit2 lineEdit2 = new LineEdit2();
  75.                 lineEdit2.setValidator(new DigitOnlyValidator());
  76.                 lineEdit2.show();
  77.         }
  78. }


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

Decorator Pattern  (0) 2014.06.27
Composite Pattern  (0) 2014.06.27
Template Method Pattern  (0) 2014.06.27
Adapter 패턴  (0) 2014.06.27
Java Singleton 선언하는법  (0) 2014.06.18

// Template Method Pattern

// - 변하지 않는 공통의 알고리즘은 부모가 public 으로 제공하고

// - 변하지 않은 코드 내부의 변해야 하는 정책만 자식이 재정의 하도록 하자.


  1. // 추상클래스 기반의 약한 결합
  2. abstract class Shape {
  3.         public final void draw() { //재정의 금지 final
  4.                 drawImpl();
  5.         }
  6.         protected abstract void drawImpl();
  7.         protected abstract Shape clone();
  8.        
  9. }
  10. class Rect extends Shape {
  11.         @Override
  12.         public void drawImpl() {
  13.                 System.out.println("Draw Rect.");
  14.         }
  15.         public Rect clone() {
  16.                 return new Rect();
  17.         }
  18.        
  19. }
  20. class Circle extends Shape {
  21.         @Override
  22.         public void drawImpl() {
  23.                 System.out.println("Draw Circle.");
  24.         }
  25.         @Override
  26.         public Circle clone() {
  27.                 return new Circle();
  28.         }
  29.        
  30. }
  31. public class Ex1 {
  32.         private static Scanner scan;
  33.  
  34.         public static void main(String...args) {
  35.                 List<Shape> list = new ArrayList<>();
  36.                 // 강한결합 : 하나의 클래스가 다른 클래스를 사용 할 때 클래스의 이름을 바로 사용
  37.                 // - 교체 불가능한 경직된 디자인
  38.                
  39.                 scan = new Scanner(System.in);
  40.                 while (true) {
  41.                         System.out.println("Choice : ");
  42.                         int cmd = scan.nextInt();
  43.                         if(cmd == 0) {
  44.                                 break;
  45.                         }
  46.                         switch (cmd) {
  47.                         case 1:
  48.                                 list.add(new Rect());
  49.                                 break;
  50.                         case 2:
  51.                                 list.add(new Circle());
  52.                                 break;
  53.                         case 8:
  54.                                 System.out.println("copy : ");
  55.                                 int idx = scan.nextInt();
  56.                                 list.add(list.get(idx).clone());
  57.                                 break;
  58. //                              switch(list.get(idx).type) {
  59. //                              case 1:
  60. //                                      list.add(new Rect());
  61. //                                      break;
  62. //                              case 2:
  63. //                                      list.add(new Circle());
  64. //                                      break;
  65. //                              }
  66.                                
  67.                         case 9:
  68.                                 for(Shape s : list) {
  69.                                         s.draw();
  70.                                 }
  71.                                 break;
  72.                         }
  73.                 }
  74.         }
  75. }


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

Composite Pattern  (0) 2014.06.27
Strategy Pattern  (0) 2014.06.27
Adapter 패턴  (0) 2014.06.27
Java Singleton 선언하는법  (0) 2014.06.18
Design Pattern 기본 원칙  (0) 2014.06.18

// 기존 클래스의 인터페이스를 변경하여 클라이언트가 요구하는 새로운 클래스를 만드는 디자인 기법

// 라이브러리를 설계할 때 사용자가 쉽게 사용할 수 있게하고, 잘못된 사용은 어렵게 해라.

// 포함 > 상속

// - 쉽게 내부구현를 바꿀 수 있다. 

// -- 사용자는 성능향상만을 느낄 수 있다.

// - 외부로 노출되는 인터페이스 API를 제어가능하다.

// -- 일반적으로 상속 이용 시 부모의 public 인터페이스를 노출해야하지만 포함은 쉽게 제어 가능하다.

// -- 잘못된 사용을 할 확률이 낮아진다.


  1. /**
  2.  * Vector class를 상속을 기반으로 한 설계
  3.  * 단점 - Vector의 인터페이스가 노출되어 의도치 않은 동작을 할 수 있다.
  4.  * @author YM,Jung
  5.  *
  6.  * @param <E>
  7.  */
  8. class Stack<E> extends Vector<E> {
  9.         // java 1.0 까지의 Stack은 이런방식으로 구현되어 있다.
  10.         // 상속을 통한 재사용을 지양하자. 컴포지션(포함)으로 사용하자.
  11.         private static final long serialVersionUID = -7937875509563141466L;
  12.  
  13.         public Stack() {
  14.         }
  15.  
  16.         public boolean empty() {
  17.                 return isEmpty();
  18.         }
  19.  
  20.         public E push(E object) {
  21.                 addElement(object);
  22.                 return object;
  23.         }
  24.  
  25.         @SuppressWarnings("unchecked")
  26.         public E pop() {
  27.                 if (elementCount == 0) {
  28.                         throw new EmptyStackException();
  29.                 }
  30.                 final int index = --elementCount;
  31.                 final E obj = (E) elementData[index];
  32.                 elementData[index] = null; // GC대상이 될 수 있게 null을 대입. 메모리 릭을 예방
  33.                 return obj;
  34.         }
  35. }
  36.  
  37. /**
  38.  * 포함을 기반으로 한 설계
  39.  *
  40.  * @author YM,Jung
  41.  *
  42.  * @param <E>
  43.  */
  44. class Stack2<E> {
  45.         private List<E> data = new ArrayList<>();
  46.        
  47.         public Stack2() {}
  48.         public E push(E obj) {
  49.                 data.add(obj);
  50.                 return obj;
  51.         }
  52.         public E pop() {
  53.                 if(data.size() == 0) {
  54.                         throw new EmptyStackException();
  55.                 }
  56.                 final int index = data.size() - 1;
  57.                 final E obj = data.get(index);
  58.                
  59.                 data.remove(index);
  60.                 return obj;
  61.         }
  62.         public boolean empty() {
  63.                 return data.isEmpty();
  64.         }
  65. }
  66. public class Ex1 {
  67.  
  68.         public static void main(String[] args) {
  69.                 Stack2<String> s = new Stack2<>();
  70.                 s.push("111");
  71.                 s.push("222");
  72.                 s.push("333");
  73.                 s.push("444");
  74.                 s.push("555");
  75.                
  76.                 while(!s.empty()) {
  77.                         System.out.println(s.pop());
  78.                 }
  79.         }
  80. }


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

Strategy Pattern  (0) 2014.06.27
Template Method Pattern  (0) 2014.06.27
Java Singleton 선언하는법  (0) 2014.06.18
Design Pattern 기본 원칙  (0) 2014.06.18
Builder Pattern  (0) 2014.06.17

+ Recent posts