2015년 10월 26일 월요일

예술 영화관 (Art Theater) 위치 및 각 홈페이지(예매 및 시간표 확인)

게시물 작성시 참고한 페이지
     SEOUL ART THEATER MAP (링크 미확인 유인물)
 
     서울 예술극장 위키
     https://namu.wiki/w/%EC%98%88%EC%88%A0%EC%98%81%ED%99%94%EA%B4%80

     서울의 예술영화관
     https://ko.foursquare.com/breezeblow/list/%EC%84%9C%EC%9A%B8%EC%9D%98-%EC%98%88%EC%88%A0%EC%98%81%ED%99%94%EA%B4%80



1. CGV 아트 하우스(무비꼴라주)
  1) 위치 및 상영시간 (전용극장 이외에는 전용관을 운영중)
    (1) 아트하우스 상암
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0014&onlyOne=91

    (2) 아트하우스 신촌아트레온
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0150&onlyOne=91

    (3) 아트하우스 명동역(전용극장)
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0105&onlyOne=91

    (4) 아트하우스 대학로
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0063&onlyOne=91

    (5) 아트하우스 강변
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0001&onlyOne=91

    (6) 아트하우스 구로
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0010&onlyOne=91

    (7) 아트하우스 여의도
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0112&onlyOne=91

    (8) 아트하우스 소풍
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0143&onlyOne=91

    (9) 아트하우스 인천
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0002&onlyOne=91

    (10) 아트하우스 압구정(전용극장)
      ▶위치
      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0040&onlyOne=91

    (11) 아트하우스 오리
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0004&onlyOne=91

    (12) 아트하우스 동수원
      ▶위치


      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0041&onlyOne=91


    (13) 아트하우스 서면(부산)
      ▶위치
      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0005&onlyOne=91

    (13) 아트하우스 센텀시티(부산)
      ▶위치
      ▶상영시간
http://section.cgv.co.kr/theater/MovieCollage/TheaterTime/Default.aspx?theaterCode=0089&onlyOne=91

  2) 홈페이지
     http://www.cgv.co.kr/arthouse/


2. KT&G 상상마당 시네마
  1) 위치 및 상영시간 (홍대기준)
      ▶위치


      ▶상영시간
https://www.sangsangmadang.com/cinema/schedule/sheduleDate.asp

  2) 홈페이지
     www.sangsangmadang.com


3. KU시네마테크
  1) 위치 및 상영시간
      ▶위치
     서울시 광진구 능동로 120


      ▶상영시간
http://www.kucine.kr/index/index.php

  2) 홈페이지
    http://www.kucine.kr/index/index.php


4. KU시네마트랩
  1) 위치(고대내 위치) 및 상영시간
      ▶위치


      ▶상영시간
http://kucinetrap.kr/index/index.php

  2) 홈페이지
    http://www.kucinetrap.kr/index/index.php


5. 롯데시네마 아르떼
  1) 위치 및 상영시간
    (1) 아르떼 건대입구
      ▶위치


      ▶상영시간
http://www.lottecinema.co.kr/LHS/LHFS/Contents/CinemaInfo/ArteSchedule.aspx?CinemaGroupCode=0010&CinemaCode=1004&ScreenType=400

    (2) 아르떼 부평
      ▶위치


      ▶상영시간
http://www.lottecinema.co.kr/LHS/LHFS/Contents/CinemaInfo/ArteSchedule.aspx?CinemaGroupCode=0010&CinemaCode=3003&ScreenType=400

    (3) 아르떼 신도림
      ▶위치


      ▶상영시간
http://www.lottecinema.co.kr/LHS/LHFS/Contents/CinemaInfo/ArteSchedule.aspx?CinemaGroupCode=0010&CinemaCode=1015&ScreenType=400

    (4) 아르떼 오투(부산대)
      ▶위치


      ▶상영시간
http://www.lottecinema.co.kr/LHS/LHFS/Contents/CinemaInfo/ArteSchedule.aspx?CinemaGroupCode=0010&CinemaCode=2011&ScreenType=400

    (5) 아르떼 주엽(일산)
      ▶위치


      ▶상영시간
http://www.lottecinema.co.kr/LHS/LHFS/Contents/CinemaInfo/ArteSchedule.aspx?CinemaGroupCode=0010&CinemaCode=3013&ScreenType=400

    (6) 아르떼 청주
      ▶위치


      ▶상영시간
http://www.lottecinema.co.kr/LHS/LHFS/Contents/CinemaInfo/ArteSchedule.aspx?CinemaGroupCode=0010&CinemaCode=4003&ScreenType=400

  2) 홈페이지
    http://www.lottecinema.co.kr/LHS/LHFS/Contents/CinemaInfo/ArteNowMovie.aspx?CinemaGroupCode=0010&CinemaCode=1004&ScreenType=400


6. 미로스페이스
  1) 위치 및 상영시간
     서울특별시 종로구 경희궁1길 1 가든플레이스빌딩 2층
      ▶위치

      ▶상영시간(블로그로 일일 업로드)
         https://www.facebook.com/mirospace1

  2) 홈페이지(없음)
    (1) 블로그 및 카페 주소
        http://www.mirospace.co.kr/
    (2) 페이스북 등 SNS
        https://www.facebook.com/mirospace1


7. 서울아트시네마
  1) 위치 및 상영시간
      ▶위치


      ▶상영시간(달력 같은 스케쥴러가 있지만 2013.5 이후로는 업데이트x)


  2) 홈페이지
     http://www.cinematheque.seoul.kr/
    ps. 시간표가 따로 없음. 맥스무비,yes24, 티켓링크에서 가능


8. 스폰지하우스 광화문
  1) 위치 및 상영시간
      ▶위치


      ▶상영시간(트윗)
         https://twitter.com/spongehouse?lang=ko

  2) 홈페이지(없음)
    (1) 블로그 및 카페 주소
       http://cafe.naver.com/spongehouse.cafe


9. 씨네코드 선재(2015.11.30 폐관예정)
  1) 위치 및 상영시간
      ▶위치


      ▶상영시간


  2) 홈페이지(없음)
    (1) 블로그 및 카페 주소
        http://cafe.naver.com/artsonjearthall


10. 아리랑시네센터
  1) 위치 및 상영시간
     http://cine.arirang.go.kr/cine/intro/map.jsp

      ▶상영시간
http://cine.arirang.go.kr/cine/movie/movie_month.jsp

  2) 홈페이지
     http://cine.arirang.go.kr/cine/index.jsp


11. 씨네큐브
  1) 위치 및 상영시간
      ▶위치
 

      ▶상영시간
http://www.icinecube.com/movie/list.jsp?flag=1
  
  2) 홈페이지
      http://www.icinecube.com/


12. 아트나인
  1) 위치 및 상영시간
      ▶위치

      http://cafe.naver.com/minitheaterartnine.cafe?iframe_url=/ArticleList.nhn%3Fsearch.clubid=25494727%26search.menuid=29%26search.boardtype=B

      ▶상영시간(네이버카페 게시판으로 관리)
http://cafe.naver.com/minitheaterartnine.cafe?iframe_url=/ArticleList.nhn%3Fsearch.clubid=25494727%26search.menuid=29%26search.boardtype=B


  2) 홈페이지(네이버카페 및 메가박스로 안내)
      www.artnine.co.kr


13. 아트하우스 모모
  1) 위치 및 상영시간
      ▶위치
     서울시 서대문구 대현동 11-1

     홈페이지 오시는길 안내
     http://www.arthousemomo.com/direction

      ▶상영시간
http://arthousemomo.com/screen_current/

  2) 홈페이지
     http://www.arthousemomo.com/


14. 영화공간주안
  1) 위치 및 상영시간
      ▶위치
      http://www.cinespacejuan.com/aboutus/location.php

      ▶상영시간
http://www.cinespacejuan.com/movie/

  2) 홈페이지
      http://www.cinespacejuan.com/


15. 인디스페이스
  1) 위치 및 상영시간
      ▶위치
      http://indiespace.tistory.com/notice/1005

      ▶상영시간
http://indiespace.kr/category/Now%20Playing

  2) 홈페이지
      http://www.indiespace.kr/


16. 필름포럼
  1) 위치 및 상영시간
      ▶위치
 

      ▶상영시간
구글에서 처리한 결과를 보여준다고 합니다. 여기에 상영시간이 표시되요

  2) 홈페이지
      http://www.filmforum.kr/

2015년 10월 25일 일요일

클래스 디자인 패턴 19. Chain of Responsibility Pattern

1. 개념
  1) 의미
     같은 입력부분의 내용에 따라 출력에 대해 다른 객체
       로 작업하여 보내야 하는 경우, 해당 패턴을 이용해서
       매칭되는 객체를 찾아서 결과를 낼수 있는 방법입니다.
     이때 사슬처럼 쭉 연결해 놓고 적절성 유무를 판단후 다음 객체로
       넘기기 때문에 체인이라 이름붙었습니다.

     좋은점은 입력시에 결과에 어떤 객체를 사용할지 생각하지 않고
       쓸수 있습니다.
      단점은 속도 문제는 있을수 있습니다.


2. 소스

  1) Trouble는 발생한 문제를 표현합니다.

public class Trouble {
    private int number;             // 트러블 번호
    public Trouble(int number) {    // 트러블의 생성
        this.number = number;
    }
    public int getNumber() {        // 트러블 번호를 얻는다.
        return number;
    }
    public String toString() {      // 트러블의 문자열 표현
        return "[Trouble " + number + "]";
    }
}


  2) Support 클래스는 발생한 문제에 대한 해결을 위해
       구현할 클래스입니다.

public abstract class Support {
    private String name;                    // 트러블 해결자의 이름
    private Support next;                   // 떠넘기는 곳
    public Support(String name) {           // 트러블 해결자의 생성
        this.name = name;
    }
    public Support setNext(Support next) {  // 떠넘길 곳을 설정
        this.next = next;
        return next;
    }
    public final void support(Trouble trouble) {  // 트러블 해결 순서
        if (resolve(trouble)) {
            done(trouble);
        } else if (next != null) {
            next.support(trouble);
        } else {
            fail(trouble);
        }
    }
    public String toString() {              // 문자열 표현
        return "[" + name + "]";
    }
    protected abstract boolean resolve(Trouble trouble); // 해결용 메소드
    protected void done(Trouble trouble) {  // 해결
        System.out.println(trouble + " is resolved by " + this + ".");
    }
    protected void fail(Trouble trouble) {  // 미해결
        System.out.println(trouble + " cannot be resolved.");
    }
}


  3) 서포트를 상속하여 연결 대상이 되는 클래스를
       작성합니다.

public class NoSupport extends Support {
    public NoSupport(String name) {
        super(name);
    }
    protected boolean resolve(Trouble trouble) {     // 해결용 메소드
        return false; // 자신은 아무 처리도 하지 않는다.
    }
}


public class LimitSupport extends Support {
    private int limit;                              // 이 번호 미만이면 해결 할수 있다.
    public LimitSupport(String name, int limit) {   // 생성자
        super(name);
        this.limit = limit;
    }
    protected boolean resolve(Trouble trouble) {         // 해결용 메소드
        if (trouble.getNumber() < limit) {
            return true;
        } else {
            return false;
        }
    }
}


public class OddSupport extends Support {
    public OddSupport(String name) {                // 생성자
        super(name);
    }
    protected boolean resolve(Trouble trouble) {    // 해결용 메소드
        if (trouble.getNumber() % 2 == 1) {
            return true;
        } else {
            return false;
        }
    }
}


public class SpecialSupport extends Support {
    private int number;                                 // 이 번호만 해결할 수 있다.
    public SpecialSupport(String name, int number) {    // 생성자
        super(name);
        this.number = number;
    }
    protected boolean resolve(Trouble trouble) {     // 해결용 메소드 
        if (trouble.getNumber() == number) {
            return true;
        } else {
            return false;
        }
    }
}


  4) 테스트 메인소스를 작성합니다.
public class Main {
    public static void main(String[] args) {
        Support alice   = new NoSupport("Alice");
        Support bob     = new LimitSupport("Bob", 100);
        Support charlie = new SpecialSupport("Charlie", 429);
        Support diana   = new LimitSupport("Diana", 200);
        Support elmo    = new OddSupport("Elmo");
        Support fred    = new LimitSupport("Fred", 300);
        // 연쇄의 형성
        alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);
        // 다양한 트러블 발생
        for (int i = 0; i < 500; i += 33) {
            alice.support(new Trouble(i));
        }
    }
}


결과 :
[Trouble 0] is resolved by [Bob].
[Trouble 33] is resolved by [Bob].
[Trouble 66] is resolved by [Bob].
[Trouble 99] is resolved by [Bob].
[Trouble 132] is resolved by [Diana].
[Trouble 165] is resolved by [Diana].
[Trouble 198] is resolved by [Diana].
[Trouble 231] is resolved by [Elmo].
[Trouble 264] is resolved by [Fred].
[Trouble 297] is resolved by [Elmo].
[Trouble 330] cannot be resolved.
[Trouble 363] is resolved by [Elmo].
[Trouble 396] cannot be resolved.
[Trouble 429] is resolved by [Charlie].
[Trouble 462] cannot be resolved.
[Trouble 495] is resolved by [Elmo].


3. 다이어그램
https://ko.wikipedia.org/wiki/Chain_of_responsibility_%ED%8C%A8%ED%84%B4

https://sourcemaking.com/design_patterns/chain_of_responsibility


4. 관련패턴
  1) Composite pattern

  2) Command Pattern

클래스 디자인 패턴 18. Visitor Pattern

1. 개념
  1) 의미
     방문자 는 데이터 구조와 처리를 분리하여 처리부분을
       방문자 라고 불리우는 형태의 구현부분에 집중하는
       형태입니다.
     예제는 Composite 패턴을 기본으로 확장합니다.


2. 소스

  1) Visitor 및 Acceptor 인터페이스

public abstract class Visitor {
    public abstract void visit(File file);
    public abstract void visit(Directory directory);
}


public interface Acceptor {
    public abstract void accept(Visitor v);
}



  2) Entry는 Acceptor를 implement 합니다.
      이외에는 기존과 같습니다.

import java.util.Iterator;

public abstract class Entry implements Acceptor {
    public abstract String getName();                                   // 이름을 얻는다.
    public abstract int getSize();                                      // 사이즈를 얻는다.
    public Entry add(Entry entry) throws FileTreatmentException {       // 엔트리를 추가
        throw new FileTreatmentException();
    }
    public Iterator iterator() throws FileTreatmentException {    // Iterator의 생성
        throw new FileTreatmentException();
    }
    public String toString() {                                          // 문자열 표현
        return getName() + " (" + getSize() + ")";
    }
}



  3) Entry를 상속하여 구현한 구현체 2개 클래스를 작성하는데
      기존에 비해 Accept 를 구현해주면됩니다.
public class File extends Entry {
    private String name;
    private int size;
    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }
    public String getName() {
        return name;
    }
    public int getSize() {
        return size;
    }
    public void accept(Visitor v) {
        v.visit(this);
    }
}


import java.util.Iterator;
import java.util.Vector;

public class Directory extends Entry {
    private String name;                    // 디렉토리의 이름
    private Vector dir = new Vector();      // 디렉토리 엔트리의 집합
    public Directory(String name) {         // 생성자
        this.name = name;
    }
    public String getName() {               // 이름을 얻는다.
        return name;
    }
    public int getSize() {                  // 사이즈를 얻는다.
        int size = 0;
        Iterator it = dir.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry)it.next();
            size += entry.getSize();
        }
        return size;
    }
    public Entry add(Entry entry) {         // 엔트리의 추가
        dir.add(entry);
        return this;
    }
    public Iterator iterator() {      // Iterator의 생성
        return dir.iterator();
    }
    public void accept(Visitor v) {         // 방문자를 받아들임
        v.visit(this);
    }
}



  4) Visitor 를 상속한 ListVisitor를 구현합니다.
import java.util.Iterator;

public class ListVisitor extends Visitor {
    private String currentdir = "";                         // 현재 주목하고 있는 디렉토리명
    public void visit(File file) {                  // 파일을 방문했을 때 호출된다.
        System.out.println(currentdir + "/" + file);
    }
    public void visit(Directory directory) {   // 디렉토리를 방문했을 때 호출된다.
        System.out.println(currentdir + "/" + directory);
        String savedir = currentdir;
        currentdir = currentdir + "/" + directory.getName();
        Iterator it = directory.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry)it.next();
            entry.accept(this);
        }
        currentdir = savedir;
    }
}


5) 예외처리 클래스와 테스트 클래스를 작성합니다.

public class FileTreatmentException extends RuntimeException {
    public FileTreatmentException() {
    }
    public FileTreatmentException(String msg) {
        super(msg);
    }
}


public class Main {
    public static void main(String[] args) {
        try {
            System.out.println("Making root entries...");
            Directory rootdir = new Directory("root");
            Directory bindir = new Directory("bin");
            Directory tmpdir = new Directory("tmp");
            Directory usrdir = new Directory("usr");
            rootdir.add(bindir);
            rootdir.add(tmpdir);
            rootdir.add(usrdir);
            bindir.add(new File("vi", 10000));
            bindir.add(new File("latex", 20000));
            rootdir.accept(new ListVisitor());              

            System.out.println("");
            System.out.println("Making user entries...");
            Directory Kim = new Directory("Kim");
            Directory Lee = new Directory("Lee");
            Directory Kang = new Directory("Kang");
            usrdir.add(Kim);
            usrdir.add(Lee);
            usrdir.add(Kang);
            Kim.add(new File("diary.html", 100));
            Kim.add(new File("Composite.java", 200));
            Lee.add(new File("memo.tex", 300));
            Kang.add(new File("game.doc", 400));
            Kang.add(new File("junk.mail", 500));
            rootdir.accept(new ListVisitor());             
        } catch (FileTreatmentException e) {
            e.printStackTrace();
        }
    }
}



결과 :
Making root entries...
/root (30000)
/root/bin (30000)
/root/bin/vi (10000)
/root/bin/latex (20000)
/root/tmp (0)
/root/usr (0)

Making user entries...
/root (31500)
/root/bin (30000)
/root/bin/vi (10000)
/root/bin/latex (20000)
/root/tmp (0)
/root/usr (1500)
/root/usr/Kim (300)
/root/usr/Kim/diary.html (100)
/root/usr/Kim/Composite.java (200)
/root/usr/Lee (300)
/root/usr/Lee/memo.tex (300)
/root/usr/Kang (900)
/root/usr/Kang/game.doc (400)
/root/usr/Kang/junk.mail (500)


3. 다이어그램
https://ko.wikipedia.org/wiki/%EB%B9%84%EC%A7%80%ED%84%B0_%ED%8C%A8%ED%84%B4

4. 관련패턴
  1) Iterator 패턴

  2) Composite 패턴

  3) Interpreter 패턴

클래스 디자인 패턴 17. Composite Pattern

1. 개념
  1) 의미
     그릇과 내용물을 동일시하여 재귀적인 구조를 만드는 패턴


2. 소스

  1) 추상 클래스이자 디렌토리 엔트리를 표현하는
      Entry 클래스를 작성.

package A2;

public abstract class Entry {
    protected Entry parent;
    public abstract String getName();
    public abstract int getSize();
    public Entry add(Entry entry) throws FileTreatmentException {
        throw new FileTreatmentException();
    }
    public void printList() {
        printList("");
    }
    protected abstract void printList(String prefix);
    public String toString() {
        return getName() + " (" + getSize() + ")";
    }
    public String getFullName() {                
        StringBuffer fullname = new StringBuffer();
        Entry entry = this;
        do {
            fullname.insert(0, "/" + entry.getName());
            entry = entry.parent;
        } while (entry != null);
        return fullname.toString();
    }
}


  2) 파일을 표현하는 file 클래스를 작성

package A2;

public class File extends Entry {
    private String name;
    private int size;
    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }
    public String getName() {
        return name;
    }
    public int getSize() {
        return size;
    }
    protected void printList(String prefix) {
        System.out.println(prefix + "/" + this);
    }
}


  3) 마찬가지로 directory 클래스를 작성
package A2;

import java.util.Iterator;
import java.util.Vector;

public class Directory extends Entry {
    private String name;
    private Vector directory = new Vector();
    public Directory(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public int getSize() {
        int size = 0;
        Iterator it = directory.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry)it.next();
            size += entry.getSize();
        }
        return size;
    }
    public Entry add(Entry entry) {
        directory.add(entry);
        entry.parent = this;              
        return this;
    }
    protected void printList(String prefix) {
        System.out.println(prefix + "/" + this);
        Iterator it = directory.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry)it.next();
            entry.printList(prefix + "/" + name);
        }
    }
}


  4) 예외를 담기위한 클래스 및 테스트 클래스
package A2;

public class FileTreatmentException extends RuntimeException {
    public FileTreatmentException() {
    }
    public FileTreatmentException(String msg) {
        super(msg);
    }
}


package A2;

public class Main {
    public static void main(String[] args) {
        try {
            Directory rootdir= new Directory("root");

            Directory bindir= new Directory("bin");
            rootdir.add(bindir);

            Directory tempdir= new Directory("tmp");
            bindir.add(tempdir);

            File file = new File("Composite.java", 100);
            tempdir.add(file);
            rootdir.printList();

            System.out.println("");
            System.out.println("file = " + file.getFullName());     
            System.out.println("tmp= " + tempdir.getFullName());     
        } catch (FileTreatmentException e) {
            e.printStackTrace();
        }
    }
}


결과 :
/root (100)
/root/bin (100)
/root/bin/tmp (100)
/root/bin/tmp/Composite.java (100)

file = /root/bin/tmp/Composite.java
tmp= /root/bin/tmp


3. 다이어그램
https://en.wikipedia.org/wiki/Composite_pattern

4. 관련패턴
  1) Command 패턴

  2) Visitor 패턴

  3) Decorator 패턴

2015년 10월 18일 일요일

클래스 디자인 패턴 16. Bridge Pattern

1. 개념
  1) 의미
     일정 기능을 담당하는 구조체에 특정 기능을 추가하는
        하나의 방법입니다.
     이를 좀더 확장하기 용이하게 하기 위해서 구현부분과
       추상부분을 분리합니다.  이후 이 두부분을
       이용해서 독립적으로 발전시킬 수 있습니다.


2. 소스

  1) 무언가 작업을 하는데 adapter 의 방법을 좀 인용한것
       같습니다. display 와 이를 상속하여 추가 구현할
       클래스 CountDisplay 을 작성합니다.
      display에서 에러나는 부분은 차후 작업합니다.
      display와 countdisplay는 기존 작업 내용을 포함하여
       새로운 기능을 추가합니다.

public class Display {
private DisplayImpl impl;
public Display(DisplayImpl impl){
this.impl = impl;
}
public void open(){
impl.rawOpen();
}

public void print(){
impl.rawPrint();
}

public void close(){
impl.rawClose();
}

public final void display(){
open();
print();
close();
}
}


public class CountDisplay extends Display {

public CountDisplay(DisplayImpl impl) {
super(impl);
}
public void multiDisplay(int times){
open();
for(int i=0; i<times;i++){
print();
}
close();
}
}


  2) displayimpl 을 작업하는 이 클래스는 추상클래스 입니다.
      기존 구현부를 담당하며 메소드를 규정합니다.

public class CountDisplay extends Display {

public CountDisplay(DisplayImpl impl) {
super(impl);
}

public void multiDisplay(int times){
open();
for(int i=0; i<times;i++){
print();
}
close();
}
}


  3) impl을 상속받아 실제 구현부를 작성합니다.

public class StringDisplayImpl extends DisplayImpl {
private String string;
private int width;
public StringDisplayImpl(String string){
this.string = string;
this.width = string.getBytes().length;
}
@Override
public void rawClose() {
printLine();
}

private void printLine() {
System.out.print("+");
for(int i=0; i<width; i++){
System.out.print("-");
}
System.out.println("+");
}
@Override
public void rawPrint() {
System.out.println("|"+string+"|");
}

@Override
public void rawOpen() {
printLine();
}
}


  4) 이를 테스트할 코드를 작성합니다.
      그냥 작성한 인스턴스를 불러서 생성할 수 있지만
      왜 이렇게 돌려서 작성하냐면 상속을 피하고
      인터페이스를 활용한 느슨한 연결을
      하고 싶어서 입니다.

public class MainTest {
public static void main(String[] args) {
Display d1 = new Display(new StringDisplayImpl("Hello, Korea"));
Display d2 = new CountDisplay(new StringDisplayImpl("Hello, World"));
CountDisplay d3 = new CountDisplay(new StringDisplayImpl("Hello, Universe"));

d1.display();
d2.display();
d3.display();
d3.multiDisplay(5);
}
}


결과 :
+------------+
|Hello, Korea|
+------------+
+------------+
|Hello, World|
+------------+
+---------------+
|Hello, Universe|
+---------------+
+---------------+
|Hello, Universe|
|Hello, Universe|
|Hello, Universe|
|Hello, Universe|
|Hello, Universe|
+---------------+


3. 다이어그램
https://ko.wikipedia.org/wiki/%EB%B8%8C%EB%A6%AC%EC%A7%80_%ED%8C%A8%ED%84%B4

4. 관련패턴
  1) Template Method 패턴

  2) Abstract Factory

  3) Adapter 패턴

2015년 10월 16일 금요일

클래스 디자인 패턴 15. Abstract Factory Pattern

1. 개념
  1) 의미
     interface를 가져와 실제로 구현을 하여 사용하는 Factory 패턴의
      확장입니다.
 

2. 소스

  1) html 페이지를 하나 작성할건데 기존처럼 단순하게
      하는 대신에 작성하는 페이지 위에 추상 클래스를 작성합니다.
      여기서는 구현부에 들어가는 각 부분을
      추상클래스로 하나의 셋트를 작성합니다.

package factory;

public abstract class Item {
protected String caption;
public Item(String caption){
this.caption=caption;
}
public abstract String makeHTML();
}


package factory;

public abstract class Link extends Item{
protected String url;
public Link(String caption, String url){
super(caption);
this.url=url;
}
}


package factory;

import java.util.Vector;

public abstract class Tray extends Item {
protected Vector tray = new Vector();
public Tray(String caption){
super(caption);
}
public void add(Item item){
tray.add(item);
}
}

package factory;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Vector;

public abstract class Page {
protected String title;
protected String author;
protected Vector content = new Vector<>();

public Page(String title, String author){
this.title=title;
this.author=author;
}

public void add(Item item){
content.add(item);
}
public void output(){
String filename = title +".html";
try {
Writer writer = new FileWriter(filename);
writer.write(this.makeHTML());
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(filename +"을 작성햇습니다.");
}
public abstract String makeHTML();
}

package factory;

public abstract class Factory {
public static Factory getFactory(String classname){
Factory factory = null;
try {
factory = (Factory) Class.forName(classname).newInstance();
} catch (Exception e) {
System.out.println("class is : "+classname +" 이 발견되지 않았습니다.");
}
return factory;
}
public abstract Link createLink(String cpation, String url);
public abstract Tray createTray(String caption);
public abstract Page createPage(String title, String author);
}


  2) 이를 사용해서 test를 진행할 main 클래스를 작성합니다.
       이후 에러는 나지 않지만 실행시 클래스가 없다고 나옵니다.
       현재 구현한 부분은 실행되지 않는 추상적인 부분밖에 없어서
       그렇습니다.

package noname;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class MainTest {
public static void main(String[] args) {
if(args.length!=1){
System.out.println("Usage : Java main class.name.of.ConcreateFactory");
System.out.println("example 1:  java main listfacoty.ListFActory");
System.out.println("example 2:  java main tableFactory.TableFactory");
System.exit(0);
}
Factory factory = Factory.getFactory(args[0]);

Link joins = factory.createLink("중앙일보", "http://www.joins.com/");
Link hani = factory.createLink("한겨례 신문", "http://www.hani.co.kr/");
Link us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
Link kr_yahoo = factory.createLink("Yahoo!Korea", "http://www.yahoo.co.kr");
Link excite = factory.createLink("Excite", "http://www.excite.com/");
Link google = factory.createLink("google", "http://www.google.com/");

Tray traynews = factory.createTray("newspaper");
traynews.add(joins);
traynews.add(hani);

Tray trayyahoo = factory.createTray("Yahoo!");
trayyahoo.add(us_yahoo);
trayyahoo.add(kr_yahoo);

Tray traysearch = factory.createTray("서치엔진");
traysearch.add(trayyahoo);
traysearch.add(excite);
traysearch.add(google);

Page page = factory.createPage("LinkPage", "kim kmi kkim");
page.add(traynews);
page.add(traysearch);
page.output();
}
}


  3) 지금까지 작성한 추상클래스를 상속받아 아래와 같이
      구현 클래스를 작성합니다.
       ListFactory 클래스는 factory에서 지정한 함수에서
       각자 추상 클래스를 상속받은 인스턴스를 생성해서
       넘겨주는 역할을 합니다.

package listfactory;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class ListFactory extends Factory {

@Override
public Link createLink(String cpation, String url) {
return new ListLink(cpation, url);
}

@Override
public Tray createTray(String caption) {
return new ListTray(caption);
}

@Override
public Page createPage(String title, String author) {
return new ListPage(title, author);
}
}




  4) 각 추상클래스를 상속받아 실제 코드를 기입한
      부분입니다.
package listfactory;

import factory.Link;

public class ListLink extends Link {

public ListLink(String caption, String url) {
super(caption, url);
}

@Override
public String makeHTML() {
return "<li><a href=\""+url+"\">"+caption+"</a></li>\n";
}
}


package listfactory;

import java.util.Iterator;

import factory.Item;
import factory.Tray;

public class ListTray extends Tray {

public ListTray(String caption) {
super(caption);
}

@Override
public String makeHTML() {
StringBuffer buffer = new StringBuffer();
buffer.append("<li>\n");
buffer.append(caption+"\n");
buffer.append("<ul>\n");
Iterator it = tray.iterator();

while(it.hasNext()){
Item item = (Item) it.next();
buffer.append(item.makeHTML());
}
buffer.append("</ul>\n>");
buffer.append("</li>\n");
return buffer.toString();
}
}


package listfactory;

import java.util.Iterator;

import factory.Item;
import factory.Page;

public class ListPage extends Page {

public ListPage(String title, String author) {
super(title, author);
}

@Override
public String makeHTML() {
StringBuffer buffer = new StringBuffer();
buffer.append("<html><head><title>"+ title +"</title></head>\n");
buffer.append("<body>\n");
buffer.append("<h1>"+ title +"</h1>\n");
buffer.append("</ul>\n");
Iterator it = content.iterator();
while(it.hasNext()){
Item item = (Item) it.next();
buffer.append(item.makeHTML());
}
buffer.append("</ul>\n");
buffer.append("<hr><address>"+author+"</address>");
buffer.append("</body></html>\n");
return buffer.toString();
}
}




결과 : 실행시 argument 에 listfactory/ListFactory 를 넣어준다.
         콘솔로 실행시에는 java listfactory/ListFactory.java
         를 넣어줘야 정상적으로 실행된다.

LinkPage.html을 작성햇습니다.


해당 파일 실행시 다음 결과를 확인 할 수 있습니다.
   여기서 중요한 점은 추상 클래스 셋트를 상속하여
   다른 구현 클래스를 추가시에 다른 소스 변동없이 다른
   페이지 구성을 할 수가 있습니다.

LinkPage

  • newspaper >
  • 서치엔진 >

  • kim kmi kkim



    3. 다이어그램


    4. 관련패턴
      1) Builder 패턴
          인터페이스가 정해져 있는 추상적인 부품을 구현해 나가는 형태이며
          Builder 패턴은 단계를 밟아나가면서 대규모의
          인스턴스를 만들어 나갑니다.

      2) Factory Method 패턴
          제품, 부품을 만드는 형태는 Factory Method와 같습니다.

      3) Composite 패턴
          만들어진 결과물은 Composite 패턴이 되는 경우가 있습니다.

      4) Singleton 패턴
          구체정인 공장은 Singleton 패턴이 되는 경우가 있습니다.

    클래스 디자인 패턴 14. Builder

    1. 개념
       구조를 가지는 인스턴스를 쌓아 올리는 Builder 패턴
     
     



    2. 소스

      1) 문서를 생성하는 기능을 작성하고자 하는데 여기서
         문서의 메서드를 강제하는 Builder abstract Class 를 생성


    public abstract class BuilderO {
    public abstract void makeTitle(String titile);
    public abstract void makeString(String str);
    public abstract void makeItems(String[] items);
    public abstract Object getResult();
    }


      2) bulder를 사용하는 Director를 작성

    public class Director {
    private BuilderO builder;

    public Director(BuilderO builder){
    this.builder = builder;
    }

    public Object construct(){
    builder.makeTitle("Greeting");
    builder.makeString("morning and afternoon");
    builder.makeString("at night");
    builder.makeItems(new String[]{
    "Hello",
    "good night",
    "see you late"});
    return builder.getResult();
    }
    }


      3) builder를 상속하여 작성하는 첫번째 텍스트 빌더를생성

    public class TextBuilder extends BuilderO {
    private StringBuffer buffer = new StringBuffer();

    @Override
    public void makeTitle(String title) {
    buffer.append("========================\n");
    buffer.append("┌"+title +"┘\n");
    buffer.append("\n");
    }

    @Override
    public void makeString(String str) {
    buffer.append("■"+str+"\n");
    buffer.append("\n");
    }

    @Override
    public void makeItems(String[] items) {
    for(int i=0; i<items.length;i++){
    buffer.append("~"+items[i]+"\n");
    }
    buffer.append("\n");
    }

    @Override
    public Object getResult() {
    buffer.append("======================");
    return buffer.toString();
    }

    }


      4) 역시 builder를 상속받아 작성하는 html 빌더를 작성
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;


    public class HtmlBuilder extends BuilderO {
    private String filename;
    private PrintWriter writer;
    @Override
    public void makeTitle(String title) {
    filename = title +".html";
    try{
    writer = new PrintWriter(new FileWriter(filename));
    }catch(IOException e){
    e.printStackTrace();
    }
    writer.println("<html><head><title>"+title+"</title></head><body>");
    writer.println("<h1>"+title+"</h1>");
    }

    @Override
    public void makeString(String str) {
    writer.println("<p>"+str+"</p>");
    }

    @Override
    public void makeItems(String[] items) {
    writer.println("<ul>");
    for(int i=0; i<items.length;i++){
    writer.println("<li>"+items[i]+"</li>");
    }
    writer.println("</ul>");

    }

    @Override
    public Object getResult() {
    writer.println("</body></html>");
    writer.close();
    return filename;
    }

    }


      5) 테스트 클래스를 작성
    public class MainTest {
    public static void main(String[] args) {
    if(args.length !=1){
    usage();
    System.exit(0);
    }

    if(args[0].equals("plain")){
    Director director = new Director(new TextBuilder());
    String result = (String) director.construct();
    System.out.println(result);
    }else if(args[0].equals("html")){
    Director director = new Director(new HtmlBuilder());
    String filename = (String) director.construct();
    System.out.println(filename + "이 작성되었습니다.");
    }else{
    usage();
    }
    }

    private static void usage() {
    System.out.println("Usage : java main plain ");
    System.out.println("Usagfe : java main html ");
    }
    }


    결과 1 :  main 의 인자로들어가는 argument str[] 에
             옵션을 줘야지만 정상적인 테스트가 가능함

         run 에 argument 로 plain 부여시
    ========================
    ┌Greeting┘

    ■morning and afternoon

    ■at night

    ~Hello
    ~good night
    ~see you late

    ======================

    결과 2 : run 옵션 argument 에 html 부여시

    Greeting.html이 작성되었습니다.

    and
    프로젝트 페이지에 다음 파일이 생성됨
    그리고 해당 파일 실행시 아래처럼 페이지가 뜸

    Greeting

    morning and afternoon
    at night
    • Hello
    • good night
    • see you late


    3. 다이어그램



    4. 관련패턴
      1) Template Method 패턴
          builder에서는 director 가 builder를 조정하지만
           Template 에서는 상위 클래스가 하위 클래스를 조정

      2) 생성 결과물이 Composite 패턴이 되는 경우가 있습니다.

      3) Facade 의 인터페이스를 director 가 제공해줘서 규격을
          통일 시킵니다.

    클래스 디자인 패턴 13. Prototype pattern

    1. 개념
      1) 의미
         new 연산자를 사용하면서 클래스를 지정하지 않고 인스턴스를
           생성하려는 경우 클래스가 아닌 기존의 인스턴스를
           복사해야 하는 경우가 있습니다.
         목적 인스턴스가 취급하는 객체가 여러개인 경우, 복잡한
           과정을 통해서 인스턴스가 생성되거나 사용자 작업으로
           인스턴스가 생성되어 이를 클래스에서 재생성이 불가한
           경우 사용하고 있는 클래스와 별도로 관리하고자 하는 경우
           가 있습니다.
         인스턴스로 새로운 인스턴스를 생성하는걸 Prototype Pattern
           이라고 합니다.
       
      2) 참고자료
         Prototype pattern 위키백과    https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85_%ED%8C%A8%ED%84%B4


    2. 소스
     
      1) 인스턴스를 사용할 수 있게 할 Product 클래스 작성
           여기서 어떤 메서드가 인스턴스를 복사할지 강제합니다.

    public interface Product extends Cloneable{
    public abstract void use(String s);
    public abstract Product createClone();
    }


      2) Product 를 이용해서 인스턴스를 실제로 복제하는 기능을
          담당하는 Manager 클래스 작성

    import java.util.Hashtable;

    public class Manager {
    private Hashtable showcase = new Hashtable();

    public void register(String name, Product proto){
    showcase.put(name,  proto);
    }

    public Product create(String protoname){
    Product p = (Product) showcase.get(protoname);
    return p.createClone();
    }
    }


      3) 인스턴스 복제 목적 클래스인 MessageBox 클래스 작성
           여기서 CreateClone에서 사용한 clone 메서드는
           자바에서 제공하는 자신의 인스턴스 복제 메서드 입니다.
           clone 사용시 Cloneable을 상속해야 합니다. (여기서는
          Product가 해당 업무를 대신함)
           그리고 clone는 해당 인스턴스 만을 복사하기 때문에
           추가적인 정보까지 같이 복사해야 하는 경우엔 해당
           clone 메서드를 오버라이드 해야합니다.

    public class MessageBox implements Product {
    private char decochar;
    public MessageBox(char decochar){
    this.decochar=decochar;
    }

    @Override
    public void use(String s) {
    int length = s.getBytes().length;
    for(int i=0; i<length; i++){
    System.out.print(decochar);
    }
    System.out.println(" ");
    System.out.println(decochar+" "+s+" "+decochar);
    for (int i=0; i<length+4;i++){
    System.out.print(decochar);
    }
    System.out.println("");
    }

    @Override
    public Product createClone() {
    Product p =null;
    try{
    p = (Product)clone();
    }catch (CloneNotSupportedException e){
    e.printStackTrace();
    }
    return p;
    }
    }


      4) 이를 테스트 하기 위한 코드
           여기서 객체 셋팅 부분은 이전에 진행된 부분이고
           주목할 점은 Product 만 가지고 클래스 상관없이
           인스턴스를 복사해서(register), 쓸수(use) 있습니다
           

    public class MainTest {
    public static void main(String[] args) {

    //객체 셋팅
    Manager manager = new Manager();
    MessageBox mbox = new MessageBox('*');
    MessageBox sbox = new MessageBox('/');
    manager.register("warning box", mbox);
    manager.register("team is good", sbox);
    //기존에 만들어진 객체를 사용하는 부분
    Product p2 = manager.create("warning box");
    p2.use("team is good");
    Product p3 = manager.create("team is good");
    p3.use("hello, southAfrica");
    }
    }


    결과 : 
    ************
    * team is good *
    ****************
    //////////////////
    / hello, southAfrica /
    //////////////////////



    3. 다이어그램

    https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85_%ED%8C%A8%ED%84%B4


    4. 관련패턴
      1)Flyweight 패턴
          Prototype은 현재 인스턴스와 같은 다른 인스턴스를 생성해서
           복사한 인스턴스를 사용하는데
         Flyweight 의 경우엔 한 인스턴스를 등록 후 이걸 여러
           장소에서 공유해서 사용합니다.

      2) Memento 패턴
        이 패턴은 undo, 스냅샷 같은 이전으로 돌아가는 명령을
           실행하도록 현재 인스턴스 상태를 보존합니다.

      3) Composite 및 Decorator
        위 패턴 사용시에 Prototype 패턴을 이용해서 구현시
          반복작업을 감소시킵니다.

      4) Command 패턴
       명령 복제시 Prototype패턴이 사용되는 경우가 이습니다.