2015년 11월 30일 월요일

WebSphere6.1 + MSSQL 2005 설정 방법

1. WebSphere6.1 설치
    상용일 경우 여기에 Java 및 HTTP 서버, 기타 여러 프로그램이 포함되어 있다.

2. WebSphere6.1 마이너 버전 업그레이드
    마이너 버전 역시 같이 있는데
    이건 미리 해당 버전 .apk 파일을 받아놓은 뒤
    update.bat 를 실행시켜서 해당 서버(appserver) 위치를 지정하고
    해당 .apk 파일을 넣으면 된다.

3. mssql 2005 설치
   이건 간단하다. 다만 ssmess 라는 관리콘솔 프로그램이 따로 있는데
    오렌지나 여타 접속 프로그램 없이 이거 하나로 다 해결하는듯 싶다.

4. WebSphere6.1 에 mssql 2005 연동
    전제 : mssql 에 유저설정, db 접속방법(윈도,계정접속을 같이),
      클라이언트 및 서버 접속 설정에 tcp/ip가 열려 있고
      방화벽에 예외 추가를 하던지 아니면 아예 사용하지 않아
      해당 부분에서는 문제가 없어야 한다는 점.
     (옆 컴에서 접속 가능하면 된다.)

    연동방법은 아래 링크를 참고 약간 맨붕이었던게
    mssql은 6.1 마이너 버전 17이상만 지원한다는 것(인터넷에서 주서들음)
    두번째로 mssql 이라는 항목이 있음에도 불구하고
    가이드에는 기타 db로 잡도록 안내하고 있다는 점이다.
   그리고 db 설정후에 꼭 서버를 재기동 해야한다.



2015년 11월 24일 화요일

MSSql + Java, Jsp(Eclipse) Driver 설정하는 것들

ps. Mssql 무려 2005 버전을 처음 사용하게 되어
    한글 설정 안한다고 좋아했는데 생각지도 않은 예스, 노 스위치
         설정때문에 많은 시간을 허비하다니....


1. 우선 jar 파일을 다운로드 해야 되는데 현재 최신은 4.2 인가함
    https://msdn.microsoft.com/en-us/sqlserver/aa937724.aspx

    근데 압축 풀면 알겠지만 java 버전별로 구별해서 넣어줘야
     말썽이 없음.
    이하 자바 버전의 경우 sqljdbc 파일명은 같은데
     2.0 이하 버전의 압축 파일을 갖다가 써야
     한다고 함.

   여기서는 1.5이기 때문에 그대로 진행
 자바는 희한하게 클래스 패스를  .jar 까지 잡아줘야 된다는
    설명이 압도적으로 많음
 하지만 결국엔 굳이 패스 안잡아도 프로젝트 안에 넣던지
     마지막처럼 서버 lib 앞에 넣어주면 됨.

 드라이버가 제대로 로드 안되면 이렇게 메시지가 뜸
java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver
at


2. 드라이버 문제가 없는데 이제는 연결을 못한다는 메시지가 계속 뜸
    처음엔 드라이버가 불량인줄 알았으나 찾아볼 수 있는 상위 드라이버는
    하위 드라이버를 정상적으로 포함한다는걸 뒤늦게 깨달음
   
  이때부터는 메시지가 이렇게 바뀜

호스트 localhost, 포트 1433에 대한 TCP/IP 연결에 실패했습니다. 오류: "Connection refused: connect. 연결 속성을 확인하십시오. SQL Server의 인스턴스가 호스트에서 실행되고 있고 포트에서 TCP/IP 연결을 허용하고 있는지 확인하십시오. 또한 방화벽에서 포트로의 TCP 연결을 차단하지 않는지 확인하십시오.".

  1) 이때 MSSql Server 2005 의 설정을 진행하기로 함
먼저 SQL Server Configuration Manager 를 실행하고 나오는 좌측
   메뉴의 위쪽부터 살펴보기로 함
   (1) Sql Server, SQL Server Browser 은 실행 중 상태여야 함
       의외로 아닌경우가 많음 그리고 우측 마우스 키 눌러서 속성에 보면
       서비스가 로컬인지 네트웍인지 보여주는데 네트웍으로 해둠
       (자컴으로 하면 상관없지만)


   (2) 바로 밑의 SQL Server 네트워크 구성의 Express 프로토콜 부분에서
        VIA 제외하고는 모두 사용으로 하고, 특히 TCP/IP 속성을 확인해서
        기본 포트를 1433으로 해둬야 함. 접속하고 있는 IP번호에
        꼭 예외를 넣어야 될 경우에 넣으면 되지만
        개발자가 굳이 ... 노멀하게 쓸때는 가장 하단 부 IP주소 부분의
        TCP 포트를 적어줘야 한다. (이 부분때문에 애먹음)


    (3) SQL Native Client 구성 부분에서도 TCP/IP를 사용하도록 설정하고
        (VIA빼고 다) 여기서도 TCP/IP 속성에 포트를 1433으로 설정한다.


   
  2) 방화벽을 체크해 줘야함.
      보통 기본으로 설치시 해당 폴더에 있으니 그대로
      해당 파일을 예외 시켜주면 됨


그랬더니 성공

3. Path 까지 잡고 SQL2005 설정 다 잡고 해당 .jar를 넣었는데도
     jsp 파일에서는 에러가 유지됨.
    결론 : 다 필요없고 Server 상 lib에 넣어두면
            자바건 jsp 건 다 됨.
            (Apache Tomcat 기준)
     끝

오류 메시지:
java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver
at

2015년 11월 16일 월요일

클래스 디자인 패턴 0.2 Design Pattern 설계 구상(문서 편집기 설계)

ps. 글 작성시 참고한 사항
   알라딘 책 설명
http://www.aladin.co.kr/shop/wproduct.aspx?ISBN=8945072144?partner=googlek&EKAMS=realclick.757.2659.141.1406787890725.2242158&trackingDays=1&gclid=CIKkusPPgskCFYGbvAod4U8NPg



1. 서두
   만약 문서 편집기를 구현해야 한다면 어떤 방식으로
     설계를 고민해야 할까.
   GoF 에서는 Lexi 라는 문서편집기를 예제로 설명함.
     여기서도 이를 따름
   아래 내용은 0장 에서 설명한 내용대로 구현을
      고민한 결과임.

2. 문서 편집기가 꼭 가져야 할 기능
  1) 문서 구조
  2) 서식 설정
  3) 사용자 인터페이스 꾸미기
  4) 여러 룩앤필 표준 지원
  5) 여러 윈도우 시스템 지원
  6) 사용자 조작(command 의 이동 관련)
  7) 철자 검사 및 붙임표 처리


3. 구현 방향은?
  1) 문서 구조
     - 문자, 그림, 은 각각 객체에 담겨야 되고 이 객체는
        차별없이 편집기 안의 행, 열에 담겨야 된다.
     - 이를 위해서는 행, 열 에 대한 정의가 있어야 되고
     - 객체는 모두 인터페이스나 추상 클래스로 통합되어야 한다.
   결론 : 문서 구조를 위해서는 복잡채 패턴(Composite) 이 적용가능함

  2) 서식 설정
     - 문서는 각각 서식을 지닐 수 있으나 서식은 문서 구조와는
         독립적임
   결론 : 전략(Stratege ) 패턴의 적용을 고려가능함

  3) 사용자 인터페이스 장식
     - 화면안의 사각형 및 메뉴를 보여줘야 되는데 이는
        프로그램 실행히 항상 보여줘야 되므로
        문서 구조가 이를 상속받도록 하되 해당
        내용이 다치지 않도록 장식자 패턴을 고려할 만함
    결론 : 장식자 패턴(Decorator)을 이용

4) 다양한 룩앤룩 표준 지원
     - 버튼, 메뉴, 스크롤바 등의 객체를 같은 방식으로
        지원 할 수 있도록 추상 팩토리 패턴을 이용할 수 있다.
    결론 : 추상 팩토리(Abstract Factory) 패턴을 이용

5) 다중 윈도우 시스템 지원
     - 다양한 룩앤룩 표준은 시스템마다 다를수 있으나
         웹에 보여지는 기능은 비슷하기 때문에
         이를 셋팅하여 해당 OS 마다 차별 지원되도록 고려해야함
    결론 : 가교 (Bridge) 패턴을 이용

  6) 사용자 조작
     - 각 메뉴별, 사용자 입력에 대한 기능이 있을것이며,
        또한 뒤로 가기 버튼이나 기능을 통해 이전 상태로
        돌리는 기능을 포함하여야 함
    결론 : 명령(Command) 패턴을 사용 가능함

  7) 철자 검사 및 붙임표 연결
     - 글을 작성한 문서 전체를 스캔하여 문자, 단어를 구별하고
        이를 사전에 대입할수 있어야 함 이를 위해서
        파일 또는 객체에 접근 후 순회 하고 이를 가공해
        작업할 수 있어야 함
    결론 : 방문자(Visitor) 패턴을 활용가능


   


3.

2015년 11월 9일 월요일

클래스 디자인 패턴 0. Design Pattern 서두 (GoF 디자인 패턴 1장 내용)

ps. 글 작성시 참고한 사항
   GoF 디자인 패턴 의 서두 부분
https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4_(%EC%B1%85)

   알라딘 책 설명
http://www.aladin.co.kr/shop/wproduct.aspx?ISBN=8945072144?partner=googlek&EKAMS=realclick.757.2659.141.1406787890725.2242158&trackingDays=1&gclid=CIKkusPPgskCFYGbvAod4U8NPg


1. 의미
    프로그램 작성시 재사용이 가능한 경험을 정리 한것


2. 이론
  1) 디자인 패턴이 포함해야 할 사항들
    디자인 패턴의 이름
    특정 상황에서 자주 발생하는 문제 정의
    이를 해결하는 방법 및 과정
    해결 결과

  2) 작성 목적
    디자인 패턴은 생성, 구조, 행동 의 목적을 지니고 작성된다.

  3) 프로그램
    프로그램은 객체(또는 객체들)로 만들어진다.

  4) 객체
    객체는 데이터와 프로시저(method, 기능) 의 집합이며
      이 객체는 사용자 요청에 의해 데이터 내용이나 프로시저를
      사용자에게 제공하게 된다.

  5) 프로그램 설계시 전반적인 측면에서 고려할 사항
    캡슐화
    크기 정하기
    종속성
    유연성
    성능
    변경 가능성 혹은 진화
    재사용성

  6) 타입
    특정 인터페이스를 나타낼 때 사용함
    A 타입은 A interface에 정의한 method 를 다 처리가능함을 나타냄
    (1) 서브타입 : 다른 인터페이스를 포함하는 인터페이스
    (2) 슈퍼타입 : 서브타입의 반대개념

  7) 동적 바인딩
     요청 + 요청에 대한 처리 객체를 뭘로 연결할지
      실행하는 시점에서 결정하는 것
      이게 되는걸 가지고 다형성 이라는 표현을 쓴다.

  8) 클래스
     구현을 명세(정의) 해 놓은것
     객체의 내부 데이터, 표현 방법, 연산을 정의함

  9) 객체
     클래스를 인스턴스로 만듬으로서 생성됨
     = 클래스의 인스턴스
      객체의 내부 데이터에 대해서 메모리내 공간을 할당하고
      상태 및 연산을 처리할 수 있게 함

  10) 클래스 상속
    다른 기존 클래스를 기반으로하는 클래스를 생성가능함
    (1) 부모클래스 : 기존 클래스
    (2) 서브클래스 : 기존 클래스를 기반으로 생성한 클래스

  11) 추상 클래스
    일부는 interface 일부는 구현함
      다만 미구현 부분이 있기 때문에 인스턴스 생성이
      불가한 클래스
   
  12) 구체 클래스 : 추상 클래스의 반대개념

  13) 오버라이드
    서브 클래스에서 상속받은 연산을 재정의 하는 경우
      이를 오버라이드 라고 함

  14) 클래스 상속과 인터페이스 상속
    (1) 클래스 상속
      미리 정의된 객체를 바탕으로 작성
      클래스를 그대로 쓰고자 할때 좋다.
      재구현을 할 필요가 없다.
      부모 클래스 변경시 작식 클래스도 같이 변경된다.
    (2) 인터페이스 상속
      어떤 객체가 다른 객체 대신에 사용할 수 있는지 지정
      기능이 다른 경우에도 호환이 되야 되는경우 사용
      재구현을 해야되지만 변경에 대해 클래스 상속보다 자유롭다.

  15) 내가 사용해야 할 디자인 패턴을 고르는 방법
    (1) 패턴이 문제를 해결하는 과정을 파악
    (2) 패턴의 의도를 확인
    (3) 패턴들간 관련성을 확인
    (4) 비슷한 패턴을 학습
    (5) 내가 작성중인 프로그램 재설계의 원인은?
    (6) 이후 필요한 변경(가변성)은 무엇인지 확인


3. 패턴의 이름, 의미, 분류
-----------생성에 관련된 패턴 Creational Patterns ------------
  1) 추상 팩토리 Abstract Factory
     구체적인 클래스 지정하지 않고 작성,
       이때 관련성있는 객체를 묶거나 서로 독립적이긴 하나
       업무적으로 필요한 객체를 묶도록 인터페이스를 제공하는 패턴
http://magmajjame.blogspot.kr/2015/10/15-abstract-factory-pattern.html

  2) 빌더 Builder
     객체 표현과 생성을 분리하여
       같은 생성 방법으로 때에 따라 다른 객체를
       생성하도록 제어하는 패턴
http://magmajjame.blogspot.kr/2015/10/14-builder.html

  3) 팩토리 메서드 Factory Method
    인터페이스는 미리 정리해 놓되 실제 구현 클래스는
      서브 클래스에서 결정하도록 생성을 위임하는 방법
http://magmajjame.blogspot.kr/2015/08/4-factory-pattern.html

  4) 원형 Prototype
    객체 생성이 복잡한 경우, 또는 해당 객체의 초기값이
      계속 사용되어야 하는 경우 이를 처음 객체를 생성해 놓고
      이를 복사한 새로운 객체를 프로그램에서
      사용하도록 제어하는 패턴
http://magmajjame.blogspot.kr/2015/10/13-prototype-pattern.html

  5) 단일체 Singleton
     객체를 하나만을 가지고 여러 자원에서 활용해야하는경우
       해당 객체 생성은 1번만 하고 이 인스턴스를
       여러 지점에서 접근할 수 있도록 접촉점을 제공하는 패턴
http://magmajjame.blogspot.kr/2015/08/5-singletone-pattern.html


-----------구조에 관련된 패턴 Structural Patterns ------------
  6) 적응자 Adapter
    다른 호환되지 않는 클래스를 사용자가 원하는
      형태의 객체로 동작하도록 도와주는 패턴
http://magmajjame.blogspot.kr/2015/09/7.html

  7) 가교 Bridge
    구현부의 추상층을 분리하여 각자 독립적이거나 다른
      구현 및 변형이 가능도록 하는 패턴
http://magmajjame.blogspot.kr/2015/10/16-bridge-pattern.html

  8) 복합체 Composite
    객체는 트리 구조로 구성되어 있는 상태에서 사용자가
      단일, 복합 객체 모두 접근할 수 있도록 작성한 패턴
http://magmajjame.blogspot.kr/2015/10/17-composite-pattern.html

  9) 장식자 Decorator
    상황, 용도를 기존 객체에 추가해 다시 만드는 방법으로
      객체에 기능을 확장하는 패턴
http://magmajjame.blogspot.kr/2015/06/3.html

  10) 퍼사드 Facade
    서브 시스템의 자원을 통합한 상위 단위의 인퍼테이스를
      제공하는 패턴
http://magmajjame.blogspot.kr/2015/10/7-2-facade-pattern.html

  11) 플라이급 flyweight
     객체를 공유하여 메모리 소모를 줄이는 패턴
http://magmajjame.blogspot.kr/2015/11/22-flyweight-pattern.html

  12) 프록시 Proxy
     직접 객체로 접근하는것을 방지하고 다른 경로로
       통제된 상태로 해당 객체의 허가된 자원을
       접근할 수 있도록 하는 패턴
http://magmajjame.blogspot.kr/2015/09/11-proxy-pattern.html

-----------행동에 관련된 패턴 Behavioral Patterns ------------
  13) 책임 연쇄 Chain of Responsibility
    요청이 어느 객체에 해당되는지에 대한 판단을 해서
      해당 요청을 처리하는 책임연쇄 기능을 작성하여
      하나의 요청으로 여러 요청을 처리할 수 있게 작성하는 패턴
http://magmajjame.blogspot.kr/2015/10/19-chain-of-responsibility-pattern.html

  14) 명령 Command
    요청을 객체 형태로 캡슐화 하고 몇가지 요청, 로깅, 연산 취소 등의
      기능을 추가함
http://magmajjame.blogspot.kr/2015/09/6-command-pattern.html

  15) 해석자 Interpreter
    정의 언어 표현수단과 이를 해석하여 실행하는 해석기
      정의를 포함한 패턴
http://magmajjame.blogspot.kr/2015/11/23-interpreter-pattern.html

  16) 반복자 Iterator
    어떤 객체의 원소(데이터나 인스턴스집합)을
      순차적으로 접근할 수 있게 작성하는 패턴
http://magmajjame.blogspot.kr/2015/09/9-iterator-pattern.html

  17) 중재자 Mediator
    서로 참조해야 하는 또는 한 집합의 객체를 직접 참조하지
      않도록 중간에 중재자를 정의하여 공유 객체에서
      이를 중재하도록 하는 패턴
http://magmajjame.blogspot.kr/2015/11/20-mediater-pattern.html

  18) 메멘토 Memento
    뒤로가기 기능을 정의하는 패턴
http://magmajjame.blogspot.kr/2015/11/21-memento-pattern.html

  19) 감시자 Observer
    공유해야 할 데이터를 한곳에서 수정하고
      내용을 필요로 하는 다른 여러곳으로 공유하는 패턴
http://magmajjame.blogspot.kr/2015/06/2-observer-pattern.html

  20) 상태 State
    객체 상태 값에 따라 다른 응답이나 요청을 실행할 수 있도록
      설정한 패턴
http://magmajjame.blogspot.kr/2015/09/10-state-pattern.html

  21) 전략 Strategy
    비슷하지만 다른 결과나 동작을 보이는 내용을 묶어서
      요청하는 쪽의 상태나 속성에 따라 다른 인스턴스를
      생성하여 다른 행동을 진행하도록 묶어주는 패턴
http://magmajjame.blogspot.kr/2015/05/1-strategy-pattern.html

  22) 템플릿 메서드 Template Method
    연산에 대한 뼈대를 상위에서 정의하고 구체적인 행동은
      서브 클래스에 미루는 패턴 이는 각 서브클래스에서 재정의하여
      목적에 맞는 행동을 각각 구현하는 방법
http://magmajjame.blogspot.kr/2015/09/8-template-method-pattern.html

  23) 방문자 Visitor
    객체 구조를 이루는 원소에 대해 수행할 연산을 표현하는 패턴
http://magmajjame.blogspot.kr/2015/10/18-visitor-pattern.html

2015년 11월 6일 금요일

클래스 디자인 패턴 23. Interpreter Pattern

1. 개념
  1) 의미
     목적상 변경이 이루어질때 기존 코드를 수정하지 않고
       통역 역할을 하는 프로그램을 만들어 실행하는 패턴입니다.


2. 소스

  1) Node 추상 클래스 작성

public abstract class Node {
    public abstract void parse(Context context) throws ParseException;
}
     

     이를 상속하여 각 문법 하나하나에 대응하는
       객체들을 생성한다.

// <program> ::= program <command list>
public class ProgramNode extends Node {
    private Node commandListNode;
    public void parse(Context context) throws ParseException {
        context.skipToken("program");
        commandListNode = new CommandListNode();
        commandListNode.parse(context);
    }
    public String toString() {
        return "[program " + commandListNode + "]";
    }
}


import java.util.Vector;

// <command list> ::= <command>* end
public class CommandListNode extends Node {
    private Vector list = new Vector();
    public void parse(Context context) throws ParseException {
        while (true) {
            if (context.currentToken() == null) {
                throw new ParseException("Missing 'end'");
            } else if (context.currentToken().equals("end")) {
                context.skipToken("end");
                break;
            } else {
                Node commandNode = new CommandNode();
                commandNode.parse(context);
                list.add(commandNode);
            }
        }
    }
    public String toString() {
        return "" + list;
    }
}


// <command> ::= <repeat command> | <primitive command>
public class CommandNode extends Node {
    private Node node;
    public void parse(Context context) throws ParseException {
        if (context.currentToken().equals("repeat")) {
            node = new RepeatCommandNode();
            node.parse(context);
        } else {
            node = new PrimitiveCommandNode();
            node.parse(context);
        }
    }
    public String toString() {
        return node.toString();
    }
}


// <repeat command> ::= repeat <number> <command list>
public class RepeatCommandNode extends Node {
    private int number;
    private Node commandListNode;
    public void parse(Context context) throws ParseException {
        context.skipToken("repeat");
        number = context.currentNumber();
        context.nextToken();
        commandListNode = new CommandListNode();
        commandListNode.parse(context);
    }
    public String toString() {
        return "[repeat " + number + " " + commandListNode + "]";
    }
}


// <primitive command> ::= go | right | left
public class PrimitiveCommandNode extends Node {
    private String name;
    public void parse(Context context) throws ParseException {
        name = context.currentToken();
        context.skipToken(name);
        if (!name.equals("go") && !name.equals("right") && !name.equals("left")) {
            throw new ParseException(name + " is undefined");
        }
    }
    public String toString() {
        return name;
    }
}


  2) 구문 해석에 필요한 Context 클래스를 작성합니다.
      그 하단은 exception 처리 클래스 입니다.

import java.util.*;

public class Context {
    private StringTokenizer tokenizer;
    private String currentToken;
    public Context(String text) {
        tokenizer = new StringTokenizer(text);
        nextToken();
    }
    public String nextToken() {
        if (tokenizer.hasMoreTokens()) {
            currentToken = tokenizer.nextToken();
        } else {
            currentToken = null;
        }
        return currentToken;
    }
    public String currentToken() {
        return currentToken;
    }
    public void skipToken(String token) throws ParseException {
        if (!token.equals(currentToken)) {
            throw new ParseException("Warning: " + token + " is expected, but " + currentToken + " is found.");
        }
        nextToken();
    }
    public int currentNumber() throws ParseException {
        int number = 0;
        try {
            number = Integer.parseInt(currentToken);
        } catch (NumberFormatException e) {
            throw new ParseException("Warning: " + e);
        }
        return number;
    }
}


public class ParseException extends Exception {
    public ParseException(String msg) {
        super(msg);
    }
}


  3) 테스트 코드 입니다.

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) {
        try {
            BufferedReader reader = new BufferedReader(new FileReader("program.txt"));
            String text;
            while ((text = reader.readLine()) != null) {
                System.out.println("text = \"" + text + "\"");
                Node node = new ProgramNode();
                node.parse(new Context(text));
                System.out.println("node = " + node);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


결과 : text는 실제 내용 node는 해석 결과
node = [program []]
text = "program go end"
node = [program [go]]
text = "program go right go right go right go right end"
node = [program [go, right, go, right, go, right, go, right]]
text = "program repeat 4 go right end end"
node = [program [[repeat 4 [go, right]]]]
text = "program repeat 4 repeat 3 go right go left end right end end"
node = [program [[repeat 4 [[repeat 3 [go, right, go, left]], right]]]]

3. 다이어그램
http://zetawiki.com/wiki/Interpreter_%ED%8C%A8%ED%84%B4


4. 관련패턴
  1)

클래스 디자인 패턴 22. Flyweight Pattern

1. 개념
  1) 의미
     객체를 가볍게 하기 위한 패턴 메모리를
        좀더 적게 사용하여 객체를 표현하는 방법을 다룹니다.


2. 소스

  1)  txt 파일로 0~9까지 큰 숫자를 작성합니다.



  2) 숫자를 char로 받아서 해당 txt 파일을 확인하는 BigChar  클래스를
     작성합니다.

package a;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BigChar {
    // 문자의 이름
    private char charname;
    // 큰 문자를 표현하는 문자열('#' '.' '\n'의 열)
    private String fontdata;
    // 생성자
    public BigChar(char charname) {
        this.charname = charname;
        try {
        //System.out.println("big"+charname +".txt");
            BufferedReader reader = new BufferedReader(
                new FileReader("big" + charname + ".txt")
            );
            String line;
            StringBuffer buf = new StringBuffer();
            while ((line = reader.readLine()) != null) {
                buf.append(line);
                buf.append("\n");
            }
            reader.close();
            this.fontdata = buf.toString();
        } catch (IOException e) {
            this.fontdata = charname + "?";
        }
    }
    // 큰 문자를 표시한다.
    public void print() {
        System.out.print(fontdata);
    }
}




  3) BigCharFactory 클래스를 작성합니다. 이 클래스는
      bigchar 클래스의 인스턴스를 공유, 및 생성합니다.

package a;
import java.util.Hashtable;

public class BigCharFactory {
    // 이미 만들어진 BigChar의 인스턴스를 관리
    private Hashtable pool = new Hashtable();
    // Singleton 패턴
    private static BigCharFactory singleton = new BigCharFactory();
    // 생성자
    private BigCharFactory() {
    }
    // 유일한 하나의 인스턴스를 얻는다.
    public static BigCharFactory getInstance() {
        return singleton;
    }
    // BigChar의 인스턴스 생성(공유)
    public synchronized BigChar getBigChar(char charname) {
        BigChar bc = (BigChar)pool.get("" + charname);
        if (bc == null) {
            bc = new BigChar(charname); // 여기에서 BigChar의 인스턴스를 생성
            pool.put("" + charname, bc);
        }
        return bc;
    }
}


  4) BigString 클래스에서는 큰 숫자 인스턴스를 이용해
      화면에 뿌려줍니다.

package a;
public class BigString {
    // "큰 문자"의 배열
    private BigChar[] bigchars;
    // 생성자
    public BigString(String string) {
        bigchars = new BigChar[string.length()];
        BigCharFactory factory = BigCharFactory.getInstance();
        for (int i = 0; i < bigchars.length; i++) {
            bigchars[i] = factory.getBigChar(string.charAt(i));
        }
    }
    // 표시
    public void print() {
        for (int i = 0; i < bigchars.length; i++) {
            bigchars[i].print();
        }
    }
}


  5) 테스트 를 위한 클래스입니다.
      argument 에 숫자를 넣으면 결과에 큰숫자를 보여주게끔
     작성합니다.

package a;
public class Main {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Usage: java Main digits");
            System.out.println("Example: java Main 1212123");
            System.exit(0);
        }

        BigString bs = new BigString(args[0]);
        bs.print();
    }
}



결과 : (블로그라 좀 찌그러져 보입니다.
....######....
....##......##....
...............##....
.........####.....
...............##.....
....##......##....
....######....
.........................

3. 다이어그램
https://ko.wikipedia.org/wiki/%ED%94%8C%EB%9D%BC%EC%9D%B4%EC%9B%A8%EC%9D%B4%ED%8A%B8_%ED%8C%A8%ED%84%B4


4. 관련패턴
  1) Proxy 패턴
       인스턴스 생성에 시간이 거리는 경우 인스턴스를 공유하여
        처리 속도를 향상시킬 수 있습니다.
       Proxy 에서는 대리인을 내세워 처리 속도를 올립니다.

  2) Composite 패턴
       Composite의 Leaf 역활을 담당할 수 있습니다.

  3) Singleton 패턴
       Singleton 패턴이 Factory 역할을 겸할 수 있습니다.
       하나의 인스턴스를 가지는 Singleton이 여러곳에서
       공유되는 점이 비슷합니다.

2015년 11월 3일 화요일

협업도구?팀프로젝트관리?3.캔버스

1. 캔버스
  1) 의미
     캔버스는 그림을 그릴때 쓰는 종이다. 
     https://ko.wikipedia.org/wiki/%EC%BA%94%EB%B2%84%EC%8A%A4
    
     요즘 협업도구 라는 용어에 관심이 가서 이전부터 쓰이는거 말고
      (Office Access 나 jira, redmind 정도) 좀더 간단하고
      굳이 it 가 아니더라도 학습 시간을 적게 사용하여 
      활용할 수 있는게 있을가 싶어서 찾던중 발견하게 된 아이템

  2) 특징
    (1) 이건 이전에 소개한 트렐로나 콜라비와는 다른 영역임
           화이트보드를 큰거 하나주고 도구를 이용해 그리거나
           하여 이 큰 판을 구성원들과 공유하고 
           수정하는 정도의 기능

    (2) 물론 일을 받거나 주거나 하지도 않고 할당도 하지 않는다.

    (3) 타임라인이 있고 (작업시 팀원들에게 알림이 감)
          공동 공간에 작성된 하나의 화면을 팀원과 공유함
          + 팀원간 카톡처럼 채팅 기능이 있음.

    (4) 작성이 간단하고 어느 사무실에나 화이트 보드는 많으면
          많을수록 좋고 뭔가 구조도를 여기저기 그려놓으면
          아직 구현하지 않았지만 마음이 차분해지므로 
          좋은 툴이라고 생각함


  3) 이용방법
      여기도 아래 링크로 가서 가입 후 프로젝트를 만들면 
       프로젝트 밑에 캔버스가 하나 생기며 프로젝트를 클릭시
       하얀 판과 좌측에 메뉴를 부여해준다. 이걸로 그리면 됨
      사용한도는 생상한 캔버스 + 첨부파일 용량에 따르며 무료
       정책으로는 300M까지 사용 가능하다.

2. 사용해보기(이용하는 방법)


   처음 들어오면 위와 같은 상황 화면이 뜨는데
    각 프로젝트 안에 하나 이상의 화이트 보드가 존재하는
     형태로 구성되어 있다.

   여기서 프로젝트를 만들고 밑에 캔버스를 만들수도 있고
     만들어진 프로젝트내에 캔버스를 추가할 수도 있고
    
   탭중에 공유 캔버스를 선택시 다른이가 작성한 캔버스를
     볼수도 있다.

   캔버스중 하나를 클릭하면

    위와 같이 몇가지 도구를 제공하고 빈 화면을 제공한다.
      누군가가 열심히 작성하여 내용을 팀원들이 공유하면 끝

    공유를 위해서는 

    캔버스 위의 공유하기 버튼을 누른뒤 해당 링크를 공유하면 된다.
       상단의 공유시 권한도 부여가능하다.
  

3. 결론
   화이트 보드로 그리기 좋은 느낌은 살릴 수 없지만
     (화이트 보드로 업무를 공유하는 주된 이유가 뭔가
       빈 화면에 만들어내는 느낌 아닐까?)
   같은 내용을 팀원들 모두 확인 가능하고 
     다른 장소에서도 확인할 수 있다는 점은 강점으로 보임
     

2015년 11월 2일 월요일

클래스 디자인 패턴 21. Memento Pattern

1. 개념
  1) 의미
     문서 편집이나 그림 작업시 이전 상태로 되돌리기 위해서는
       이전 상태에 대한 정보가 남아 있어야 됩니다.
     Memento 패턴은 이전 상태를 담아두되
       인스턴트 상태를 나타내는 역할을 부여해 보존, 복원이
       실행되도록 하는 패턴입니다.


2. 소스

  1) Memento class
       현재 상태를 표현하는 클래스입니다.
package game;
import java.util.Vector;

public class Memento {
    int money;                  
         // 돈
    Vector fruits;            
        // 과일
    public int getMoney() {
       // 돈을 얻는다.(narrow interface)
        return money;
    }
    Memento(int money) {
       // 생성자(wide interface)
        this.money = money;
        this.fruits = new Vector();
    }
    void addFruit(String fruit) {
       // 과일을 추가한다.(wide interface)
        fruits.add(fruit);
    }
}


  2) Gamer 클래스
      현재 뭔가 작업이 이루어지는 클래스
      여기에서는 난수 및 시간을 딜레이 하는 기능을 이용해
      일정 시간별로 한 사이클씩 작업이 이루어집니다.

package game;
import java.util.Vector;
import java.util.Iterator;
import java.util.Random;

public class Gamer {
    private int money;                          // 소유한 돈
    private Vector fruits = new Vector();       // 과일
    private Random random = new Random();       // 난수발생기
    private static String[] fruitsname = {      // 과일 이름의 표
        "사과", "포도", "바나나", "귤",
    };
    public Gamer(int money) {                   // 생성자
        this.money = money;
    }
    public int getMoney() {                     // 현재의 돈을 얻는닫.
        return money;
    }
    public void bet() {                         // 졌다...게임의 진행
        int dice = random.nextInt(6) + 1;           // 주사위를 던진다.
        if (dice == 1) {                            // 1이 나온다...돈이 증가한다.
            money += 100;
            System.out.println("돈이 증가했습니다.");
        } else if (dice == 2) {                     // 2가 나온다...돈이 반으로 준다.
            money /= 2;
            System.out.println("돈이 반으로 줄었습니다.");
        } else if (dice == 6) {                     // 6이 나온다...과일을 받는다.
            String f = getFruit();
            System.out.println("과일(" + f + ")을 받았습닏다.");
            fruits.add(f);
        } else {                                    // 그 밖에...아무 일도 일어나지 않는다.
            System.out.println("아무일도 일어나지 않았습니다.");
        }
    }
    public Memento createMemento() {                // 스냅샷을 찍는다.
        Memento m = new Memento(money);
        Iterator it = fruits.iterator();
        while (it.hasNext()) {
            String f = (String)it.next();
            if (f.startsWith("맛있다.")) {         // 과일은 맛있는 것만 보존
                m.addFruit(f);
            }
        }
        return m;
    }
    public void restoreMemento(Memento memento) {       // undo를 실행한다.
        this.money = memento.money;
        this.fruits = memento.fruits;
    }
    public String toString() {                      // 문자열 표현
        return "[money = " + money + ", fruits = " + fruits + "]";
    }
    private String getFruit() {                     // 과일을 1개 얻는다.
        String prefix = "";
        if (random.nextBoolean()) {
            prefix = "맛있다.";
        }
        return prefix + fruitsname[random.nextInt(fruitsname.length)];
    }
}



  3) 테스트 메인소스를 작성합니다.
      여기서는 작업이 진행된 상태를 사이클이 지날때마다
      보여주는 작업도 같이 합니다.
import game.Memento;
import game.Gamer;

public class Main {
    public static void main(String[] args) {
        Gamer gamer = new Gamer(100);               // 처음의 돈은 100
        Memento memento = gamer.createMemento();    // 처음의 상태를 보존해 둔다.
        for (int i = 0; i < 100; i++) {
            System.out.println("==== " + i);        // 횟수 표시
            System.out.println("현 상태:" + gamer);    // 현재의 주인공의 상태 표시

            gamer.bet();    // 게임을 진행 시킨다.

            System.out.println("돈은" + gamer.getMoney() + "원이 되었습니다.");

            // Memento의 취급 결정
            if (gamer.getMoney() > memento.getMoney()) {
                System.out.println("    (많이 증가했으니 현재의 상태를 보존해두자)");
                memento = gamer.createMemento();
            } else if (gamer.getMoney() < memento.getMoney() / 2) {
                System.out.println("    (많이 줄었으니 이전의 상태로 복귀하자)");
                gamer.restoreMemento(memento);
            }

            // 시간을 기다림
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            System.out.println("");
        }
    }
}


결과 :
==== 0
현 상태:[money = 100, fruits = []]
아무일도 일어나지 않았습니다.
돈은100원이 되었습니다.

==== 1
현 상태:[money = 100, fruits = []]
아무일도 일어나지 않았습니다.
돈은100원이 되었습니다.

==== 2
현 상태:[money = 100, fruits = []]
아무일도 일어나지 않았습니다.
돈은100원이 되었습니다.

==== 3
현 상태:[money = 100, fruits = []]
아무일도 일어나지 않았습니다.
돈은100원이 되었습니다.
1
==== 4
현 상태:[money = 100, fruits = []]
돈이 증가했습니다.
돈은200원이 되었습니다.
    (많이 증가했으니 현재의 상태를 보존해두자)

==== 5
현 상태:[money = 200, fruits = []]
과일(맛있다.포도)을 받았습닏다.
돈은200원이 되었습니다.

==== 6
현 상태:[money = 200, fruits = [맛있다.포도]]
과일(귤)을 받았습닏다.
돈은200원이 되었습니다.

........


3. 다이어그램

https://en.wikipedia.org/wiki/Memento_pattern

http://scotty83.tistory.com/entry/Memento-Pattern

4. 관련패턴
  1) Command 패턴
      undo, redo를 Memento 패턴을 사용해서 구현가능합니다.

  2) Prototype 패턴
    스냅샷 및 undo 기능을 추가하기 위해 Memento 패턴을
      넣을 수 있습니다.

  3) State 패턴
    상태를 포현한다는 점에선 같으나 State는 클래스 자체가 상태를
      표현하며 Memento는 인스턴스가 상태를 표현합니다.

클래스 디자인 패턴 20. Mediater Pattern

1. 개념
  1) 의미
     공동작업시 공유된 자원을 조정하는 조정자 역할을 하는 패턴
       상호간에 통신이 필요할때 꼭 조정자로 지정한 객체를 통해서
       통신하도록 정보를 집중하는 패턴
       GUI 에서 많이 사용함


2. 소스

  1) Mediattor 인터페이스
      해당 인터페이스는 조정자 역할을 담당할 클래스의
      interface를 정의합니다.
     이를 구현한 구현체는 LoginFrame이라는 클래스로 구현합니다.

public interface Mediator {
    public abstract void createColleagues();
    public abstract void colleagueChanged(Colleague colleague);
}


import java.awt.Frame;
import java.awt.Label;
import java.awt.Color;
import java.awt.CheckboxGroup;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class LoginFrame extends Frame implements ActionListener, Mediator {
    private ColleagueCheckbox checkGuest;
    private ColleagueCheckbox checkLogin;
    private ColleagueTextField textUser;
    private ColleagueTextField textPass;
    private ColleagueButton buttonOk;
    private ColleagueButton buttonCancel;

    // 생성자
    // Colleague들을 생성해서 배치한 후에 표시를 실행한다.
    public LoginFrame(String title) {
        super(title);
        setBackground(Color.lightGray);
        // 레이아웃 매니저를 사용해서 4*2의 그리드를 만든다.
        setLayout(new GridLayout(4, 2));
        // Colleague들의 생성
        createColleagues();
        // 배치
        add(checkGuest);
        add(checkLogin);
        add(new Label("Username:"));
        add(textUser);
        add(new Label("Password:"));
        add(textPass);
        add(buttonOk);
        add(buttonCancel);
        // 유효/무효의 초기지정
        colleagueChanged(checkGuest);
        // 표시
        pack();
        show();
    }

    // Colleague들을 생성한다.
    public void createColleagues() {
        // 생성
        CheckboxGroup g = new CheckboxGroup();
        checkGuest = new ColleagueCheckbox("Guest", g, true);
        checkLogin = new ColleagueCheckbox("Login", g, false);
        textUser = new ColleagueTextField("", 10);
        textPass = new ColleagueTextField("", 10);
        textPass.setEchoChar('*');
        buttonOk = new ColleagueButton("OK");
        buttonCancel = new ColleagueButton("Cancel");
        // Mediator의 세트
        checkGuest.setMediator(this);
        checkLogin.setMediator(this);
        textUser.setMediator(this);
        textPass.setMediator(this);
        buttonOk.setMediator(this);
        buttonCancel.setMediator(this);
        // Listener의 세트
        checkGuest.addItemListener(checkGuest);
        checkLogin.addItemListener(checkLogin);
        textUser.addTextListener(textUser);
        textPass.addTextListener(textPass);
        buttonOk.addActionListener(this);
        buttonCancel.addActionListener(this);
    }

    // Colleague로부터의 통지로 각 Colleague의 유효/무효를 판정한다.
    public void colleagueChanged(Colleague c) {
        if (c == checkGuest || c == checkLogin) {
            if (checkGuest.getState()) {             // Guest 모드
                textUser.setColleagueEnabled(false);
                textPass.setColleagueEnabled(false);
                buttonOk.setColleagueEnabled(true);
            } else {                                 // Login 모드
                textUser.setColleagueEnabled(true);
                userpassChanged();
            }
        } else if (c == textUser || c == textPass) {
            userpassChanged();
        } else {
            System.out.println("colleagueChanged:unknown colleague = " + c);
        }
    }
    // textUser 또는 textPass의 변경이 있었다.
    // 각 Colleague의 유효/무효를 판정한다.
    private void userpassChanged() {
        if (textUser.getText().length() > 0) {
            textPass.setColleagueEnabled(true);
            if (textPass.getText().length() > 0) {
                buttonOk.setColleagueEnabled(true);
            } else {
                buttonOk.setColleagueEnabled(false);
            }
        } else {
            textPass.setColleagueEnabled(false);
            buttonOk.setColleagueEnabled(false);
        }
    }
    public void actionPerformed(ActionEvent e) {
        System.out.println("" + e);
        System.exit(0);
    }
}


  2) Colleague 인터페이스 및 구현체들
      해당 구현체는 Mediator에게 뭔가 정보를 요구하거나
      정보를 요청하는 사용자들입니다.

public interface Colleague {
    public abstract void setMediator(Mediator mediator);
    public abstract void setColleagueEnabled(boolean enabled);
}


import java.awt.Button;

public class ColleagueButton extends Button implements Colleague {
    private Mediator mediator;
    public ColleagueButton(String caption) {
        super(caption);
    }
    public void setMediator(Mediator mediator) {            // Mediator를 보관
        this.mediator = mediator;
    }
    public void setColleagueEnabled(boolean enabled) {      // Mediator가 유효/무효를 지시한다.
        setEnabled(enabled);
    }
}


import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;

public class ColleagueCheckbox extends Checkbox implements ItemListener, Colleague {
    private Mediator mediator;
    public ColleagueCheckbox(String caption, CheckboxGroup group, boolean state) {  // 생성자
        super(caption, group, state);
    }
    public void setMediator(Mediator mediator) {            // Mediator를 보관
        this.mediator = mediator;
    }
    public void setColleagueEnabled(boolean enabled) {      // Mediator가 유효/무효를 지시한다.
        setEnabled(enabled);
    }
    public void itemStateChanged(ItemEvent e) {             // 상태가 변하면 Mediator에게 통지
        mediator.colleagueChanged(this);
    }
}


import java.awt.TextField;
import java.awt.Color;
import java.awt.event.TextListener;
import java.awt.event.TextEvent;

public class ColleagueTextField extends TextField implements TextListener, Colleague {
    private Mediator mediator;
    public ColleagueTextField(String text, int columns) {
        // 생성자
        super(text, columns);
    }
    public void setMediator(Mediator mediator) {
       // Mediator를 보관
        this.mediator = mediator;
    }
    public void setColleagueEnabled(boolean enabled) {
      // Mediator가 유효/무효를 지시한다.
        setEnabled(enabled);
        setBackground(enabled ? Color.white : Color.lightGray);
    }
    public void textValueChanged(TextEvent e) {
     // 문자열이 변하면 Mediator에게 통지
        mediator.colleagueChanged(this);
    }
}


  3) 테스트 메인소스를 작성합니다.
public class Main {
    static public void main(String args[]) {
        new LoginFrame("Mediator Sample");
    }
}



결과 :



3. 다이어그램

https://en.wikipedia.org/wiki/Mediator_pattern

http://copynull.tistory.com/145

4. 관련패턴
  1) Facade 패턴
      Mediatro 가 양방향 중재자로서 인터페이스를 제공했다면
      Facade는 단방향으로 정보를 제공합니다.

  2) Observer 패턴
      통신 자체는 Observer 패턴을 이용해서 수행되는 경우가 있습니다.