2012년 4월 26일 목요일

[Java Design Pattern_3]Template Method 샘플 코드2


@ AbstractClass (추상 클래스)  

 - 이 클래스에서는 탬플릿 메소드를 구현(정의)합니다.


package Template;

public abstract class AbstractDisplay {
public final void decorate(){
   char topChar = getTopCharacter();
   char leftChar = getLeftCharacter();
   String str = getString();
   char rightChar = getRightCharacter();
   char bottomChar = getBottomCharacter();

   for(int i=0; i<str.length() + 2; i++){
       System.out.print(topChar);
   }
   System.out.println();

   System.out.print(leftChar);
   if (isUpperCase()){
       System.out.print(str.toUpperCase());
   }else{
       System.out.print(str.toLowerCase());
   }

   System.out.print(rightChar);

   System.out.println();
   for(int i=0; i<str.length() + 2; i++){
   System.out.print(bottomChar);
   }
}

protected boolean isUpperCase() {
return true;
}

protected abstract char getTopCharacter();

protected abstract char getLeftCharacter();

protected abstract String getString();

protected abstract char getRightCharacter();

protected abstract char getBottomCharacter();
}

@ ConcreateClass(구현 클래스)

-  추상 클래스에서 정의된 메소드를 구체적으로 구현 합니다.

package Template;

public class StringDisplay extends AbstractDisplay {
    @Override
    protected char getBottomCharacter() {
        return '#';
    }
    @Override
    protected char getLeftCharacter() {
        return '(';
    }
    @Override
    protected char getRightCharacter() {
        return ')';
    }
    @Override
    protected String getString() {
        return "sgdata";
    }
    @Override
    protected char getTopCharacter() {
        return '#';
    }
}

@ Main Class

package Template;

public class Main {
public static void main(String[] args) {
    AbstractDisplay decorator = new StringDisplay();
        decorator.decorate();
    }
}

2012년 4월 24일 화요일

[Java Design Pattern_5]Singleton 설명

# Singleton
-  인스턴스를 한 개만 만들기

@ Singleton 패턴

- '클래스의 인스턴스가 단 하나만 필요'한 경우에 사용하는 패턴.
- 컴퓨터 자체를 표현한 클래스, 현재의 시스템 설졍을 표현한 클래스, 윈도우 시스템을 표현한 클래스..











[Java Design Pattern_4]Factory Method 샘플 코드1





1. Framework

 - Product  클래스 : '제품'을 표현한 추상 클래스로서 추상 메서드 use만 선언 되어 있다.

 package sample.framework;  
 public abstract class Product {  
      public abstract void use();  
 }  


- Factory 클래스 : 템플릿 패턴이 적용되어 있습니다. 추상 메서드 createProduct,registerProduct는 하위 클래스에서 구현 합니다. create 메서드는 Product의 인스턴스를 생성하는 것으로 규정하고 있습니다. 즉, createProduct에서 제품을 만들어서 registerProduct에서 등록한다고 규정하고 있습니다.

 package sample.framework;  
 public abstract class Factory {  
      public final Product create(String owner) {  
           Product p = createProduct(owner);  
           registerProduct(p);  
           return p;  
      }  
      protected abstract Product createProduct(String owner);  
      protected abstract void registerProduct(Product product);  
 }  


2. Idcard

- IDCard 클래스 : Product 클래스를 상속받아서 구현.

 package sample.idcard;  
 import sample.framework.Product;  
 public class IDCard extends Product {  
      private String owner;  
      IDCard(String owner) {  
           System.out.println(owner + "의 카드를 만듭니다.");  
           this.owner = owner;  
      }  
      public void use() {  
           System.out.println(owner + "�̃의 카드를 사용합니다.");  
      }  
      public String getOwner() {  
           return owner;  
      }  
 }  


- IDCardFactory : Factory 클래스를 상속받아서 구현.

 package sample.idcard;  
 import java.util.ArrayList;  
 import java.util.List;  
 import sample.framework.Factory;  
 import sample.framework.Product;  
 public class IDCardFactory extends Factory {  
      private List owners = new ArrayList();  
      protected Product createProduct(String owner) {  
           return new IDCard(owner);  
      }  
      protected void registerProduct(Product product) {  
           owners.add(((IDCard) product).getOwner());  
      }  
      public List getOwners() {  
           return owners;  
      }  
 }  



3. Main

 package sample;  
 import sample.framework.Factory;  
 import sample.framework.Product;  
 import sample.idcard.IDCardFactory;  
 public class Main {  
      public static void main(String[] args) {  
           Factory factory = new IDCardFactory();  
           Product card1 = factory.create("홍길동");  
           Product card2 = factory.create("김민수");  
           Product card3 = factory.create("구로이드");  
           card1.use();  
           card2.use();  
           card3.use();  
      }  
 }  






[Java Design Pattern_4]Factory Method 설명


# Factory Method
- 하위 클래스에서 인스턴스 작성하기


@ Factory Method 패턴

- Template Method 패턴을 인스턴스 생성에 적용한 것이 Factory Method패턴이다.

- 인스턴스 생성을 위한 골격(framework)와 실제의 인스턴스 생성의 클래스를 분리해서 생각할수 있습니다. 인스턴스를 만드는 방법을 상위 클래스 측에서 결정, 구체적인 내용은 모두 하위 클래스 측에서 수행합니다.


@ Factory Method 패턴의 등장인물

1. Framework

 - Product(제품)  : framework 쪽의 클래스로서 만들고자(생산)하는 클래스의 API를 결정하는 추상 클래스 입니다. 구체적인 내용은 ConcreteProduct에서 구현합니다.

 - Creator(작성자) : Product를 생성하는 추상 클래스입니다. Creator가 가지고 있는 정보는 Product 역할과 인스턴스 생성 메소드뿐입니다.
  * new 를 사용해서 실제의 인스턴스를 생성하는 대신에, 인스턴스 생성을 위한 메소드를 호출해서 구체적인 클래스 이름에 의한 속박에서 상위 클래스를 자유롭게 만듭니다.

2. idcard(Concrete)

 - ConcreteProduct(구체적인 제품) : 구체적인 제품 클래스.

 - ConcreteCreator(구체적인 작성자) : 구체적인 제품을 만드는 클래스.


@예제

-  구조




1. Framework

 - Product  클래스 : '제품'을 표현한 추상 클래스로서 추상 메서드 use만 선언 되어 있다.

 - Factory 클래스 : 템플릿 패턴이 적용되어 있습니다. 추상 메서드  createProduct,registerProduct는 하위 클래스에서 구현 합니다. create 메서드는 Product의 인스턴스를 생성하는 것으로 규정하고 있습니다. 즉, createProduct에서 제품을 만들어서 registerProduct에서 등록한다고 규정하고 있습니다.

2. Idcard

- IDCard 클래스 : Product 클래스를 상속받아서 구현

- IDCardFactory : Factory 클래스를 상속받아서 구현.
                         (createProduct, registerProduct 메소드 구현)


3. Main

 - Main 클래스 : 실행 클래스


@ Think!!

 1. Framework와 Idcard 패키지를 의존하고 있지 않다.

- '추상적인 골격' '구체적인 내용'의 두가지 측면으로 Factory Method를 살펴 보았습니다. 위와 달리 IDCard외 Television을 만든다고 가정하면, TelevisionFactory 클래스(Factory 상속)와 Television 클래스(Product 상속)만 만들면 새로운 객체에 적용할 수 있습니다. 이때 Framework의 클래스(Factory, Product)는 수정할 수 필요가 없습니다.

2. 인스턴스 생성  - 메소드의 구현 방법(createProduct 메소드)

- 추상 메소드로 한다.

- 디폴트의 구현을 준비해 둔다. : 하위 클래스에서 구현하지 않았을 경우를 염두해 둔 코드. 이때 Product는 추상 클래스로 만들지 못한다.

- 에러를 이용한다.  : 하위 클래스가 구현하지 않으면 에러가 발생하도록 해둔 코드.
 [FactoryMethodRuntimeException은 별로 작성되어 있다고 가정]

[Java Design Pattern_2]Adapter 샘플 코드3_File 입출력

- Target(대상) : 상속의 경우 인터페이스로 원하는 API를 만든다.


package Adapter;


import java.io.IOException;


public interface FileIO {
public void readFromFile(String filename) throws IOException;
public void writeToFile(String filename) throws IOException;
public void setValue(String key, String value);
public String getValue(String key);
}


- Adaptee(개조되는 쪽) : 기존에 사용되고 있는 클래스로서 Target의 API에 맞게 재구현되는 클래스이다.


java.util.Properties


void load (InputStream in) throws IOException
: 속성의 집합을 InputStream에서 읽는다.


void store (OutputStream out, String header) throws IOException
: 속성의 집합을 OutputStream에 쓴다. header는 코멘트 문자열.


- Adapter(어댑터) : Adaptee와 Target을 이어주는 클래스이다.


1. 상속의 경우 타겟은 인터페이스로 Adaptee는 상속으로 받아서 변환시킨다.



package Adapter;


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;


public class FileProperties extends Properties implements FileIO{
public void readFromFile(String filename) throws IOException{
load(new FileInputStream(filename));
}

public void writeToFile(String filename) throws IOException {
store(new FileOutputStream(filename), "written by FileProperties");
}

public void setValue(String key, String value) {
setProperty(key, value);
}

public String getValue(String key) {
return getProperty(key, "");
}
}


2. 위임의 경우 Target클래스를 상속해서 Adaptee 클래스 인스턴스로 구현시킨다.



package Adapter;


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;


public class FileProperties implements FileIO{

private Properties properties;

public FileProperties(){
this.properties = new Properties();
}

public void readFromFile(String filename) throws IOException{
this.properties.load(new FileInputStream(filename));
}

public void writeToFile(String filename) throws IOException {
this.properties.store(new FileOutputStream(filename), "written by FileProperties");
}

public void setValue(String key, String value) {
this.properties.setProperty(key, value);
}

public String getValue(String key) {
return this.properties.getProperty(key, "");
}
}

- Client(의뢰자) : Target을 통해 일을 하는 클래스이다.



package Adapter;


import java.io.*;


public class Main {


public static void main(String[] args) {
FileIO f = new FileProperties();
try {
f.readFromFile("file.txt");
f.setValue("year", "2004");
f.setValue("month", "4");
f.setValue("day", "21");
f.writeToFile("newfile.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
}




[Java Design Pattern_3]Template Method 샘플 코드1

@ AbstractClass (추상 클래스)  


 - 이 클래스에서는 탬플릿 메소드를 구현(정의)합니다.

 public abstract class AbstractDisplay {  
      public abstract void open();  
      public abstract void print();  
      public abstract void close();  
      public final void display() {  
           open();  
           for (int i = 0; i < 5; i++)  
                print();  
           close();  
      }  
 }  

@ ConcreateClass(구현 클래스)


-  추상 클래스에서 정의된 메소드를 구체적으로 구현 합니다.

1. CharDisplay


 public class CharDisplay extends AbstractDisplay {  
      char ch;  
      public CharDisplay(char ch) {  
           this.ch = ch;  
      }  
      @Override  
      public void open() {  
           System.out.print("<<");  
      }  
      @Override  
      public void print() {  
           System.out.print(ch);  
      }  
      @Override  
      public void close() {  
           System.out.println(">>");  
      }  
 }  


2. StringDisplay

 public class StringDisplay extends AbstractDisplay {  
      String str;  
      public StringDisplay(String str) {  
           this.str = str;  
      }  
      @Override  
      public void open() {  
           printLine();  
      }  
      @Override  
      public void print() {  
           System.out.println("|" + str + "|");  
      }  
      @Override  
      public void close() {  
           printLine();  
      }  
      private void printLine() {  
           System.out.print("+");  
           try {  
                for (int i = 0; i < str.getBytes("euc-kr").length; i++)  
                     System.out.print("-");  
                System.out.println("+" + str.getBytes("euc-kr").length);  
           } catch (Exception e) {  
           }  
      }  
 }  



@ Main Class

 public class Main {  
      public static void main(String[] args) {  
           AbstractDisplay d1=new CharDisplay('H');  
           AbstractDisplay d2=new StringDisplay("Hello, world");  
           AbstractDisplay d3=new StringDisplay("안녕하세요.");  
           d1.display();  
           d2.display();  
           d3.display();  
      }  
 }  



[Java Design Pattern_3]Template Method 설명


# Templete Method 

- 하위 클래스에서 구체적으로 처리하기



@ 템플릿이란 무엇인가 ?  


- 템플릿이란 문자 모양으로 구멍이 뚫려있는 얇은 플라스틱 판을 말합니다. 구멍에 어떤 펜을 쓰느냐에 따라 같은 템플릿(모양)에서도 다양한 느낌을 낼수 있습니다.


@ Template Method 패턴이란


 - Template Method 패턴은 상위 클래스쪽에 탬플릿에 해당하는 메소드가 정의(주로 추상 메서드)되어 있고, 하위 클래스에서 구체적으로 구현되는 것을 말합니다. 이와 같이 상위 클래스에서 처리의 뼈대를 결정하고, 하위 클래스에서 그 구체적인 내용을 결정하는 디자인 패턴을 Template Method패턴이라고 합니다.


@ Template Method 패턴의 등장인물


 - AbstractClass (추상 클래스) : 이 클래스에서는 탬플릿 메소드를 구현(정의)합니다.

 - ConcreteClass (구현 클래스) : 추상 클래스에서 정의된 메소드를 구체적으로 구현 합니다.


@ 예제 


 - 구조





- AbstractDisplay : 템플릿 메소드 구현 및 정의.
        구체적으로 구현 되지 않은 open(),print(),close() 메소드로 display 메소드만 구현 되어 있음.(open(),print(),close() 메소드 구현은 하위 클래스에 맡김.)

- CharDisplay, StringDisplay : open(),print(),close() 구현 하는 클래스

- Main : AbstractDisplay 객체를 생성해서 사용.



@ Think!


1. 로직을 공통화 할수 있어 수정이 용이하다.


 - 상위 클래스의 템플릿 메소드에서 알고리즘(display())이 기술되어 있으므로, 하위 클래스에서 알고리즘을 일일이 기술할 필요가 없다.

 - 만약 수정 사항이 생겨도 해당 구현 클래스만 수정하면 된다. 즉, 알고리즘 수정시 상위 클래스, 구현 수정시 하위 클래스만 수정하면 된다.


2. 상위 클래스와 하위 클래스의 연계


- 상위 클래스에서 선언된 추상 메소드를 실제적으로 하위 클래스에서 구현하므로 어떤 시점에 메소드가 호출되는지 이해해야 하위 클래스에서 잘 구현할수 있다.


3. 하위 클래스를 상위 클래스에 넣어 동작시킨다.

 상위 클래스인AbstractDisplay형의 변수에 하위 클래스인 CharDisplay,StringDisplay인스턴스를 넣어 상위 클래스 템플릿 메소드은 display()를 사용한다. 이처럼 특정 인스턴스로 형변환을 하지 않고 동작하도록 하므로 어떤 하위 클래스 인스턴스를 넣어도 작동할 수 있다.


- 상속의 일반적인 원칙 -

" 상위 클래스형의 변수에 하위 클래스의 어떠한 인스턴스를 대입해도 제대로 작동할 수 있도록 한다" 
- The Liskov Substitution Principle(LSP)