반응형

자바에서 중복되지 않는 키를 생성하기 위해 자료를 찾던중 java.util.UUID 클래스를 찾았습니다.
물론 직접 랜덤 클래스등을 이용해서 만들어도 되지만 좋은 클래스가 이미 만들어져 있다면 써야지요.
구글에서 국내 자료를 검색해봤는데 겨우 2건이 검색되고 그것도 그냥 자바 API 였습니다.
그래서 간략하게나마 이 클래스에 대해 소개하겠습니다.

UUID(유니버셜 유니크 아이디)는 JDK 1.5 부터 지원됩니다.
128비트로 이루어진 unique 키를 생성할 수 있습니다.

생성자는 이렇습니다. UUID (long mostSigBits, long leastSigBits)

UUID uid = new UUID(1,2);
System.out.println(uid.toString());
결과 : 00000000-0000-0001-0000-000000000002

UUID uid = new UUID(0xaaaa,0xffff);
System.out.println(uid.toString());
결과 : 00000000-0000-aaaa-0000-00000000ffff



아래와 같이 직접 문자열로 키를 주어 생성할 수도 있습니다.

UUID uid = UUID.fromString("3051a8d7-aea7-1801-e0bf-bc539dd60cf3");



제일 중요한 것은 직접 만들어서 사용하는 것이 아닌 랜덤한 생성이겠죠.

UUID uid = UUID.randomUUID();



더 자세한 사항은 API를 보세요. :)


출처 : http://ultteky.egloos.com/10506174

반응형
반응형

의도

  ● 복잡하게 얽혀 있는 클래스나 서브시스템간의 인터페이스를 정리하여 클라이언트 측에서

      사용하기 쉽도록 포괄적이고 한 단계 높은 수준의 인터페이스를 제공함

  ● 서브시스템의 복잡한 인터페이스를 단순화된 하나의 통합 인터페이스로 제공

 

 

동기

이런 식으로 구성된 클래스라 하면 ClientClass에서 사용해야 하는 클래스나 메소드가 많아 사용방법이나 호출순서에도 신경을 많이 써야 함

 

 

 

 

 

 

Facade패턴을 이용하여 내부에서 작동하고 있는 많은 클래스들의 관계나 사용법을 의식하지 않고 Facade에서 제공하는 단순화된 하나의 인터페이스를 이용하여 같은 결과를 얻을 수 있음

 

 

 

 

 

구조

 

참여객체

 

  ○ Facade : 단순하고 일관된 통합 인터페이스 제공

      - 서브시스템의 어떤 클래스가 어떤 요청을 처리해야 하는지 알고 있으며 클라이언트의

        각 요청을 해당하는 서브시스템 객체에 전달

  ○ subsystem classes : 서브시스템의 기능성을 구현

      - Facade객체에서 할당한 작업을 실제로 처리

      - Facade에 대한 아무런 정보도 가지고 있지 않음

 

협력방법

 

  ● 클라이언트는 Facade의 인터페이스를 이용해서 서브시스템과 상호작용하므로 Facade에는

      클라이언트로부터의 요청을 서브시스템의 적당한 객체에게 전달 할 수 있는 클라이언트 요청

      에 대한 작업을 미리 정의하고 있어야 함

  ● Facade를 사용하는 클라이언트는 서브시스템의 객체로 직접 접근할 필요가 없음

 

활용성

 

  ○ 복잡한 서브시스템에 대한 단순화 된 인터페이스 제공이 필요할 때

      → 재사용성과 확장성을 고려하여 설계해 복잡해진 각각의 클래스들을 다 이해하면서 서브시

          스템을 사용할 필요가 없는 개발자들에게 단순하면서도 기본적인 인터페이스 만을 제공

  ○ 클라이언트와 구현클래스 간의 너무 많은 종속성이 존재할 때

      → Facade의 사용으로 클라이언트와 다른 서브시스템 간의 결합도를 줄일 수 있으므로

          클라이언트와 서브시스템 사이의 종속성을 감소 시킬 수 있음

  ○ 서브시스템들의 계층화를 이루고자 할 때

      → Facade는 각 서브시스템의 계층별 접근을 제공할 수 있으므로 서브시스템과 서브시스템

          간의 종속성이 있다 하더라도 Facade를 통해서만 교류하게 함으로써 서브시스템간의 종속

          성을 줄일 수 있음

         ☞ 서브시스템 내부 설계의 변경이 다른 서브시스템에 독립적으로 자유롭게 이루어질 수 있다

 

결과

 

  1. 클라이언트가 다루어야 할 객체의 수가 줄어들므로 서브시스템의 구성요소를 보호할 수 있다

  2. 서브시스템과 클라이언트 코드의 결합도를 줄일 수 있다

     서브시스템과 클라이언트간의 결합도가 낮으면 서브시스템 내 요소를 다양화 하는 작업이 원활

     해 지므로 서브시스템내에서는 결합도가 더 강해질 수 있다.

  3. 서브시스템의 클래스를 사용하는 것을 완전히 막지는 않는다.

     Facade를 사용할지 서브시스템의 클래스를 사용할지는 직접 결정할 수 있다.

 

확장

 

여러 개의 서브시스템과 Facade가 있을 때 이를 다시 Facade를 구성함으로써 더욱더 클라이언트와 서브시스템간의 의존성을 줄일수 있다.

 

 

 

 

 

Facade를 추상클래스로 정의하고 이를 상속하는 클래스를 정의하여 서브시스템마다 다른 구현을 하게 함으로써도 확장이 가능하다.

 

[출처] Facade 패턴|작성자 파람



출처: http://blog.naver.com/PostView.nhn?blogId=whistle96&logNo=140005491925

반응형
반응형

퍼사드 패턴(Facade Pattern)

정의
어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공합니다. 퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브시스템을 더 쉽게 사용할 수 있습니다.

01public class Facade {
02    // 우리가 사용하고자 하는 서브시스템의 모든 구성요소들이 인스턴스 변수 형태로 저장 됩니다.
03    DvdPlayer dvd;
04    Light light;
05    Screen screen;
06     
07    public Facade(DvdPlayer dvd, Light light, Screen screen) {
08        this.dvd = dvd;
09        this.light = light;
10        this.screen = screen;
11    }
12    // 하나하나 수동으로 작업 했던 내용들을 하나의 메소드로 순서대로 처리 합니다.
13    //  각 작업은 서브시스템에 들어있는 구성요소들에게 위임 됩니다.
14    public watchMove(String movie) {
15        dvd.on();
16        light.on();
17        dvd.open();
18        dvd.insert();
19        screen.on();
20        dvd.play();
21    }
22}


객체지향 원칙(디자인 원칙)
1. 애플리케이션에서 바뀌는 부분을 찾아내서 바뀌지 않는 부분으로부터 분리 시켜 캡슐화 한다.
2. 상속보다는 구성을 활용한다.
3. 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.
4. 서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.
5. 클래스는 확장에 대해서는 열려 있지만 변경에 대해서는 닫혀 있어야 한다.(OCP : Open-Closed Principle)
6. 추상화된 것에 의존하도록 만들어라. 구상 클래스에 의존하도록 만들지 않도록 한다. (의존성 뒤집기 윈칙:Dependency Inversion Principle)
7. 최소 지식 원칙(Principle of Least Knowledge) - 정말 친한 친구하고만 얘기하라.
- 시스템을 디자인할 때, 어떤 객체든 그 객체와 상호작용을 하는 클래스의 개수에 주의해야 하며, 그런 객체들과 어떤 식으로 상호작용을 하는지에도 주의를 기울여야 한다
- 최소 지식 원칙 단점 : 이 원칙을 적용하다 보면 다른 구성요소에 대한 메소드 호출을 처리하기 위해 "래퍼" 클래스를 더 만들어야 할 수도 있습니다. 그러다 보면 시스템이 더 복잡해지고, 개발 시간도 늘어나고, 성능이 떨어질 수도 있습니다.

7번 원칙에 대한 가이드 라인을 제시 합니다. 어떤 메소드에서든지 다음 네 종류의 객체의 메소드만을 호출 하면 됩니다.
1. 객체 자체
2. 메소드에 매개변수로 전달된 객체
3. 그 메소드에서 생성하거나 인스턴스를 만든 객체
4. 그 객체에 속하는 구성요소 

예제)
- 원칙을 따르지 않은 경우

1// station으로부터 thermometer라는 객체를 받은 다음, 그객체의
2// getTemperature() 메소드를 직접 호출 합니다.
3public float getTemp() {
4    Thermometer thermometer = station.getThermometer();
5    return thermometer.getTemperature();
6}


- 원칙을 따르는 경우 

1// 최소 지식 원칙을 적용하여 Station 클래스에 thermometer에 요청을 해 주는
2// 메소드를 추가했습니다. 이렇게 하면 의존해야 하는 클래스의 개수를 줄일 수 있죠.
3public float getTemp() {
4    return station.getTemperature();
5}



최소 지식 원칙을 따르면서 메소드를 호출하는 방법 예제

01public class Car {
02    // 클래스의 구성요서. 이 구성요소의 메소드는 호출해도 되죠.
03    Engine engine;
04    // 기타 인스턴스 변수
05     
06    public Car() {
07        // 엔진 초기화 등을 처리
08    }
09     
10    public void start(Key key) {
11        // 새로운 객체를 생성 합니다. 이 객체의 메소드는 호출해도 됩니다.
12        Doors doors = new Doors();
13        // 매개변수로 전달된 객체의 메소드는 호출해도 됩니다.
14        boolean authorized = key.turns();
15         
16        if (authorized) {
17            // 이 객체의 구성요소의 메소드는 호출해도 되죠?
18            engine.start();
19            // 객체 내에 있는 메소드는 호출해도 됩니다.
20            updateDashboardDisplay();
21            // 직접 생성하거나 인스턴스를 만든 객체의 메소드는 호출해도 됩니다.
22            doors.lock();  
23        }
24         
25    }
26     
27    public void updateDashboardDisplay() {
28        // 디스플레이 갱신
29    }
30}



어댑터 패턴과 퍼사드 패턴의 차이점
어댑터 패턴은 인터페이스를 변경해서 클라이언트에서 필요로 하는 인터페이스로 적응시키기 위한 용도
퍼사드 패턴은 어떤 서브시스템에 대한 간단한 인터페이스를 제공하기 위한 용도
퍼사드는 인터페이스를 단순화 시키기 위한 용도로 쓰이는 반면, 어댑터는 인터페이스를 다른 인터페이스로 변환하기 위한 용도로 쓰입니다.

핵심 정리
- 기존 클래스를 사용하려고 하는데 인터페이스가 맞지 않으면 어댑터를 쓰면 됩니다.
- 큰 인터페이스, 또는 여러 인터페이스를 단순화시키거나 통합 시켜야 되는 경우에는 퍼사드를 쓰면 됩니다.
- 어댑터는 인터페이스를 클라이언트에서 원하는 인터페이스로 바꿔주는 역할을 합니다.
- 퍼사드는 클라이언트를 복잡한 서브시스템과 분리시켜주는 역할을 합니다.
- 어댑터를 구현할 때는 타겟 인터페이스의 크기와 구조에 따라 코딩해야 할 분량이 결정됩니다.
- 퍼사드 패턴에서는 서브시스템을 가지고 퍼사드를 만들고, 실제 작업은 서브클래스에 맡깁니다.
- 어댑터 패턴에는 객체 어댑터 패턴과 클래스 어댑터 패턴이 있다. 클래스 어댑터를 쓸려면 다중 상속 기능이 필요 합니다.
- 한 서브시트템에 퍼사드를 여러개 만들어도 됩니다.
- 어댑터는 객체를 감싸서 인터페이스를 바꾸기 위한 용도로, 데코레이터는 객체를 감싸서 새로운 행동을 추가하기 위한 용도로, 퍼사드는 일련의 객체들을 감싸서 단순화 시키기 위한 용도로 쓰입니다.


출처 : http://outliers.tistory.com/entry  

반응형
반응형
디자인 패턴

소프트웨어 설계 시 특정 상황에서 자주 만나는 문제를 해결하기 위해 사용할수 있는 재사용 가능한 솔루션.

패턴의 설계 구조를 보면 대부분 비슷한데, 그 이휴는 두가지 구조로 정리되기 때문이다. 

하나는 클래스 상속이고 다른 하나는 오브젝트 합성이다. 

따라서 패턴의 결과로 나온 코드나 설계 구조만 보면 대부분 비슷해 보인다.

패턴에서 가장 중요한 것은 각 패턴의 핵심이 담긴 목적 또는 의도다. 패턴을 적용할 상황, 해결해야 할 문제,

솔루션의 구조와 각 요서의 역할과 함께 핵심 의도가 무엇인지를 기억해둬야 한다.


템플릿 메소드 패턴

상속을 통해 슈퍼클래스의 기능을 확장할 때 사용하는 가장 대표적인 방법이다.

변하지 않는 기능은 슈퍼클래스에 만들어 두고 자주 변경되며 확장할 기능은 추상클래스나 오버라이딩 가능한

protected메소드(=추상메소드) 등으로 만든 뒤 서브클래스에서 만들도록 한다
.

-단점 : 상속을 통하여 구현이 되므로 해당 추상 메소드가 필요한 클래스마다 상속을 받아야 한다.


 
 
=============== 예제 ================

/* UserDao.java */

public abstract class UserDao {


public void deleteAll() throws SQLException {


Connection c = null;

PreparedStatement ps = null;


try {

c = dataSource.getConnection();


ps = makeStatement(c);


ps.executeUpdate();


catch (SQLException e) {

throw e;

finally{

if(ps!=nulltry{ps.close();}catch(SQLException e){}

if(c!=nulltry{c.close();}catch(SQLException e){}

}

}


abstract protected PreparedStatement makeStatement(Connection c) throws SQLException;
}

/* UserDaoDeleteAll.java */
 public class UserDaoDeleteAll extends UserDao {


@Override

protected PreparedStatement makeStatement(Connection c) throws SQLException {

// TODO Auto-generated method stub

PreparedStatement ps = c.prepareStatement("delete from users");

return ps;

}

}
 


팩토리 메소드 패턴

템플릿 메소드와 마찬가지로 상속을 통해 기능을 확장하게 하는 패턴이다. 

허나 이 패턴의 주체는 서브클래스로 생각하면 되것다. 

서브클래스에서 오브젝트 생성 방법과 클래스를 결정할 수 있도록 미리 정의해둔 메소드를 팩토리 메소드라 하고

이방식을 통해 오브젝트 생성방법을 나머지 로직, 즉 슈퍼클래스의 기본 코드에서 독립시키는 방법 

팩토리 메소드 패턴이라 한다. 이 메소드는 주로 인터페이스 타입으로 오브젝트를 리턴한다.

자바에서 종종 오브젝트를 생성하는 기능을 가진 메소드를 일반적으로 팩토리 메소드라고


부르기도 하는데 이때 말하는 팩토리 메소드와는 다르다고 한다.

출처 http://kimddochi.tistory.com

반응형
반응형




Adapter Pattern은 겉보기에 Bridge와 비슷해 보인다.

하지만, Adapter 는 어떤 클래스의 인터페이스가 다른 코드에서 기대하는 것과 다를때 어댑터를 중간에 두어서 맞춰주는것이고, 

Bridge는 추상과 구현을 분리하는 것으로 그 의미가 명백히 구별된다.


출처 http://flyburi.com/188


반응형
반응형
반응형
반응형

브릿지 패턴은 소프트웨어 공학에서 사용되는 디자인 패턴인데, 이는 "구현(implementation)으로부터 추상(abstraction) 레이어를 분리하여 이 둘이 서로 독립적으로 변화할 수 있도록 한다."

브릿지는 캡슐화(encapsulation), 집합(aggregation)을 사용하고 또한 다른 클래스들로 책임을 분리시키기 위해 상속(inheritance)를 사용할 수 있다. 


어떤 클래스가 자주 바뀐다면(varies), 객체 지향 프로그래밍의 특징들은 아주 유용해질 수 있다. 왜냐하면 프로그램 코드를 수정하는데 프로그램에 대해 최소한만 알고도 쉽게 수정할 수 있기 때문이다. 브릿지 패턴은 어떤 클래스와 그 클래스가 하는 일이 자주 변화할 때 유용하게 사용될 수 있다. 여기에서 어떤 클래스는 구현(implementation)이라 생각할 수 있고, 그 클래스가 할 수 있는 일은 추상(abstraction)으로 생각할 수 있다. 브릿지 패턴은 추상화(abstraction)의 두 계층(layer)로 생각할 수도 있다.


브릿지 패턴은 종종 어댑터 패턴과 혼동될 수 있다. 사실, 브릿지 패턴은 종종 클래스 어댑터 패턴을 사용해서 구현되기도 한다. 아래에 나오는 자바 코드가 그 예가 될 것이다.


변종(Variant) : 추상(abstraction)이 사용되는 시점까지 구현의 존재를 미룸으로써 구현을 더욱 갈라놓을 수 있다.(정확히 이해는 안되지만 구현 객체를 최대한 늦게 생성함으로써 구현과 추상의 관계를 더욱 약하게 할 수 있다는 말인것 같네요;

원문 : The implementation can be decoupled even more by deferring the presence of the implementation to the point where the abstraction is utilized.)

구조 Structure

Abstraction - 추상 인터페이스를 정의한다. Implementor에 대한 레퍼런스를 유지한다.

RefinedAbstraction - Abstraction에 의해 정의된 인터페이스를 확장한다.(extends)

Implementor - 구현 클래스를 위한 인터페이스를 정의한다.

ConcreteImplementor - Implementor 인터페이스를 구현한다. 

예 Example

아래의 자바 프로그램은 'shape'를 이용한 예이다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/** "Implementor" */
interface DrawingAPI {
    public void drawCircle(double x, double y, double radius);
}
  
/** "ConcreteImplementor"  1/2 */
class DrawingAPI1 implements DrawingAPI {
   public void drawCircle(double x, double y, double radius) {
        System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
   }
}
  
/** "ConcreteImplementor" 2/2 */
class DrawingAPI2 implements DrawingAPI {
   public void drawCircle(double x, double y, double radius) {
        System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
   }
}
  
/** "Abstraction" */
abstract class Shape {
   protected DrawingAPI drawingAPI;
  
   protected Shape(DrawingAPI drawingAPI){
      this.drawingAPI = drawingAPI;
   }
  
   public abstract void draw();                             // low-level
   public abstract void resizeByPercentage(double pct);     // high-level
}
  
/** "Refined Abstraction" */
class CircleShape extends Shape {
   private double x, y, radius;
   public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
      super(drawingAPI);
      this.x = x;  this.y = y;  this.radius = radius;
   }
  
   // low-level i.e. Implementation specific
   public void draw() {
        drawingAPI.drawCircle(x, y, radius);
   }
   // high-level i.e. Abstraction specific
   public void resizeByPercentage(double pct) {
        radius *= pct;
   }
}
  
/** "Client" */
class BridgePattern {
   public static void main(String[] args) {
       Shape[] shapes = new Shape[] {
           new CircleShape(1, 2, 3, new DrawingAPI1()),
           new CircleShape(5, 7, 11, new DrawingAPI2()),
       };
  
       for (Shape shape : shapes) {
           shape.resizeByPercentage(2.5);
           shape.draw();
       }
   }
}





반응형
반응형

일반적인 클래스 설계


우리는 유닛 클래스를 설계해야 합니다.
이 유닛은 마린과 매딕이 존재합니다.
마린은 총을 쏘고 매딕은 주사기로 치료를 합니다.


abstract class 유닛{
    void 무기사용();
}

class 마린 : 유닛{
    void 무기사용(){총.사용하기();}
}

class 매딕 : 유닛{
    void 무기사용(){주사기.사용하기();}
}

class 총{
    void 사용하기(){발사;}
}

class 주사기{
    void 사용하기(){치료;}
}



클라이언트의 요구사항


마린도 주사기를 사용하고 매딕도 총을 사용할 수 있게 하고 싶다는 요구사항이 들어왔습니다.
그래서 상속을 이용해 아래와 같이 해결하였습니다.


abstract class 유닛{
    void 무기사용();
}

class 마린 : 유닛{
    void 무기사용();
}

class 매딕 : 유닛{
    void 무기사용();
}

class 총쏘는마린 : 마린{
    void 무기사용(){총.사용하기();}
}

class 치료하는마린 : 마린{
    void 무기사용(){주사기.사용하기();}
}

//총쏘는매딕과 치료하는매딕의 구현은 생략

class 총{
    void 사용하기(){발사;}
}

class 주사기{
    void 사용하기(){치료;}
}



그런데 다시 새로운 요구사항이 들어왔습니다.

새로 추가된 요구사항



  1. 파이어뱃의 추가 - 화염방사기를 사용함

  2. 고스트의 추가 - 총을 사용함

  3. 치료하는 파뱃, 총쏘는 파뱃, 치료하는 고스트, 화염방사기 마린...등의 구현이 필요



처음 요구사항을 해결한 방식으로 추가된 요구사항을 해결할 수 있지만 유닛과 무기가 늘어날 수록 클래스의 숫자는 폭발적으로 늘어나게 됩니다.
우리는 이 문제를 디자인 패턴을 이용하여 해결하려 합니다.

Bridge 패턴이란?




사전적인 의미

추상화 개념과 구현을 분리하여 독립적으로 변화할 수 있도록 한다

패턴을 적용할 상황

파생 클래스의 폭발적 증가 없이 다양한 구현이 필요한 상황



'알기쉬운 디자인 패턴'에 나오는 'Bridge 패턴'은 다음과 같은 기본 전략을 따르고 있습니다.


  • 무엇이 변경되는지 찾아내고 그것을 캡슐화하자

  • 상속보다는 합성을 쓰도록 노력하자



위의 내용들이 지금 당장 이해되지 않더라도 괜찮습니다.
차근차근 풀어나가 보겠습니다.

Bridge 패턴의 적용


위에서 발생한 요구사항에 따른 문제는 'Bridge 패턴'을 적용할 상황(파생 클래스의 폭발적 증가 없이 다양한 구현이 필요한 상황)에 걸맞습니다.
사전적 의미는 일단 배제하고 두가지 기본 전략을 통해 위의 예제를 분석하겠습니다.

우선 첫번째 '무엇이 변경되는지 찾아내고 그것을 캡슐화하자'
위의 예제에서 변경되는 것은 유닛이 [마린과 매딕]으로, 무기가 [총과 주사기]로 변경됩니다.
마린과 매딕은 그대로 유닛으로 두고 총과 주사기를 무기화 시킵니다.


abstract class 무기{
    void 사용하기();
}

class 총 : 무기{
    void 사용하기(){발사;}
}

class 주사기 : 무기{
    void 사용하기(){치료;}
}




두번째 전략 '상속보다는 합성을 쓰도록 노력하자'를 적용해 보겠습니다.
합성이란 것은 복잡한 것이 아니라 하나의 클래스가 다른 클래스를 포함하여 사용하게 하는 것입니다.
그렇다면 '무기가 유닛을 사용하는 것'과 '유닛이 무기를 사용하는 것'중 무엇이 맞을까요?
당연히 유닛이 무기를 사용하는 것이 맞겠죠.


//무기 클래스를 사용하도록 변경된 유닛관련 클래스
abstract class 유닛{
    무기 arms;
    유닛(무기 a){arms = a}; //생성자
    void 무기사용(){arms.사용하기();}
}

class 마린 : 유닛{
    마린(무기 a){super(a);} //생성자, super는 부모클래스
}

class 매딕 : 유닛{
    매딕(무기 a){super(a);} //생성자, super는 부모클래스
}

//무기관련 클래스는 변경사항 없슴
abstract class 무기{
    void 사용하기();
}

class 총 : 무기{
    void 사용하기(){발사;}
}

class 주사기 : 무기{
    void 사용하기(){치료;}
}



생성자를 통해서 무기를 인수로 받고 유닛 클래스의 파생 클래스(마린과 매딕)는 무기의 종류는 모르지만 사용합니다.
위의 클래스를 이용한 간단한 예제를 만들어 보겠습니다.


무기 arms = new 총();
유닛 marine = new 마린(arms);

marine.무기사용();



마린이 주사기를 사용하는 것도 문제 없겠죠?

패턴이 적용된 모습에 대한 분석


위에서 'Bridge 패턴'의 사전적 의미는 "추상화 개념과 구현을 분리하여 독립적으로 변화할 수 있도록 한다" 였습니다.
패턴의 적용으로 아래와 같은 구조를 가지게 되었습니다.

[유닛]-[마린,매딕] ---사용---> [무기]-[총,주사기]

추상화 개념은 유닛이 마린과 매딕으로 분류된다는 것이고 유닛이 무기사용에 대한 구현을 무기클래스로써 분리한 것입니다.

요구사항 해결하기


이제 'Bridge 패턴'을 적용한 클래스 설계에 새로 추가된 요구사항을 적용해 보겠습니다.


abstract class 유닛{
    무기 arms;
    유닛(무기 a){arms = a}; //생성자
    void 무기사용(){arms.사용하기();}
}

class 마린 : 유닛{
    마린(무기 a){super(a);} //생성자, super는 부모클래스
}

class 매딕 : 유닛{
    매딕(무기 a){super(a);} //생성자, super는 부모클래스
}

class 파이어뱃 : 유닛{
    파이어뱃(무기 a){super(a);} //생성자, super는 부모클래스
}

class 고스트 : 유닛{
    고스트(무기 a){super(a);} //생성자, super는 부모클래스
}

abstract class 무기{
    void 사용하기();
}

class 총 : 무기{
    void 사용하기(){발사;}
}

class 주사기 : 무기{
    void 사용하기(){치료;}
}

class 화염방사기 : 무기{
    void 사용하기(){태우기;}
}



'알기쉬운 디자인 패턴'에서의 예제는 저의 예제와 다릅니다. 책의 예제는 Adapter 패턴도 혼합되어 있습니다.
'Bridge 패턴'에 대한 설명은 이로써 마치겠습니다.
최대한 쉽고 짧게 쓴다고 노력했는데 'Bridge 패턴'을 이해하는데 도움이 되었을지 궁금하네요.
'Bridge 패턴'을 더욱 자세하게 공부하시고 싶으시다면 반드시 책을 참고하시기 바랍니다.


출처 : http://ani2life.egloos.com/2904131

이렇게 정리를 하는 님들의 열정에 정말.... 감동받습니다.

그 어떤 사실을 떠나, 박수~~~

반응형
반응형


1) .

  : 어떤 문자이건 간에 임의의 한 글자를 나타냄

  

2) * 

  : 바로 앞의 문자를 의미하며 그 문자가 없거나 하나 이상임을 나타냄

  

3) +

  : 바로 앞의 문자를 의미하며 그 문자가 하나 이상임을 나타냄

  

4) ?

  : 바로 앞의 문자가 없거나 혹은 있음을 나타냄


5) ^

  : 바로 뒤의 문자열을 기준으로 이것과 동일한 문자열로 시작되는 것을 가리킴

    

6) $

  : 문자열의 맨 마지막을 가리킴

  

7) []

  : 각괄호는 [] 안에 있는 문자열 중에서 하나의 문자만을 의미함

    [] 안에서 범위를 지정할 때는 '-' 문자를 사용함

    만일 원하지 않는 문자를 제외한 나머지 문자를 가리킬 때에는 []안의 첫 문자로 '^' 를 사용함

    

8) {} 

  : 중괄호 {} 는 {} 앞에 있는 문자나 문자열의 개수를 결정

  

9) ()

  : () 앞에 있는 글자들을 그룹화 한다.



반응형

'Java기초' 카테고리의 다른 글

replace replaceAll 차이  (0) 2014.08.01
java stack trace  (0) 2014.05.09
JVM 메모리  (0) 2014.04.30
추상클래스 인터페이스 차이2  (0) 2013.07.11
인터페이스 추상클래스  (0) 2013.07.11
반응형

인터페이스.. 추상클래스..추상메소드.. 너무복잡합니다

검색을 해도 잘 정리된 블로그는 이해할수는 있지만 정확히 뭐가뭔지 잘모를때

예제를 살펴보면 정확하게 알수 있습니다

예제를 검색해도 이해하기 어려운 부분이 있을수 있습니다

이럴때!!! 이미 잘 정리된(?) 정리라기 보다는 정의에 가까운 java api를 보면됩니다

우리가 import 해서 쓰는 클래스들 중에서 잘살펴보면 interface와 abstract 클래스와 메소드를 잘 활용한 클래스가 있습니다!

 그전에 최소한 뭐가뭔지는 알아야 되니 간단하게 정의해봤습니다

정의를 읽고난후에 설명드리겠습니다.

인터페이스란 간단히 말해서 클래스끼리 어떤방식으로 데이터를 주고받을것이냐에 대한

동작을 기술한것입니다.

일반적으로 클래스는 설계와 구현을 함께 할수있지만 인터페이스는 순수하게 설계만 하는것입니다.

 그렇다면 인터페이스를 왜 쓰는것일까요? 클래스에다가 설계와 구현을 모두할수있는데

굳이 따로할필요가 있을까라고 생각될겁니다.

예를 들자면 시간을 출력해야하는 상황에서 여러사람들이 시간을 출력하는 로직을 만들때

A라는 사람은 순수하게 시간만출력하자...

B라는 사람은 그래도 정확하게 시와 분까지만 출력하자..

C라는 사람은 무슨소리!? 초까지출력해야지!!

D라는 사람은 나라마다 다른데 나라도 명시해줘야지

라고 각자마자 생각이 다를수있습니다.

이럴때 공통사용방법을 지정하면 어디에서든 동일하게 시간을 출력하는것을 이용할수있을것입니다

(인터페이스에서는 static final 를 통해 변수를 선언할수있습니다)

이렇게 모든 클래스에서 공통으로 사용할 방법을 정의한 특별한 클래스를 interface라고

하는데 이 interface를 사용하기위해서는 implements로 사용한다고 명시해주고

interface에 정의되어있는 모든 메소드를 구현해줘야합니다.

다음으로...

그렇다면 추상클래스란 무엇이냐?

추상메소드가 하나이상 있는 클래스를 말합니다. 그렇다면 추상메소드란  무엇이냐..

public abstract void print(); 이거와 같이 {}가 없는 메소드를 말합니다

여기서 abstract를 빼줘도 에러가안납니다 뒤에 세미콜론인 ;으로 구분해주기때문에

하지만 알아보기쉽게하기위해서 abstract를 붙여주엇네요

추상클래스는 extends를 이용해서 사용할수있습니다

이제 간단한 정의 설명은 마치고 실제로 그렇게 사용되는지 왜그렇게 사용되었는지 알아보겠습니다

jadclipse를 plugin을 통해 설치안한분은 제 블로그에있는 나와있는 jadclipse 플러그인 설치 한후에 하면 훨씬 유용합니다.

일단 아무이유없이 Calender 클래스를 이용하여 날짜를 갑자기 출력하고싶어졌습니다

public class TestInterface {

    public static void main(String[] args) {
        Calendar cal =new Calendar(); //     <---- 하면어떻게될까여? Cannot instantiate the type Calendar 와 같이 오류가 뜹니다
    

    }

}

그렇다면 왜 오류가날까..컨트롤을 누른상태에서 Calender이부분을 왼쪽버튼으로 클릭해줍니다

(jad 설치시에만 가능 jad는 역컴파일러로 .class파일을 .java파일로 바꿔줍니다

그때 .class파일에 정의되어있는 Calender클래스를 보게끔 해주는 역활을 합니다)

윗부분만 조금만 보면 알수있는 사실들이 있습니다

public abstract class Calendar     //사실 1 :사실 Calender클래스는 추상클래스였다....

    implements Serializable, Cloneable, Comparable  //interface 세개를 implements를 사용하여 쓰고있다...
{
    private static class CalendarAccessControlContext
    {

        private static final AccessControlContext INSTANCE;

        static
        {
            RuntimePermission runtimepermission = new RuntimePermission("accessClassInPackage.sun.util.calendar");
            PermissionCollection permissioncollection = runtimepermission.newPermissionCollection();
            permissioncollection.add(runtimepermission);
            INSTANCE = new AccessControlContext(new ProtectionDomain[] {
                new ProtectionDomain(null, permissioncollection)
            });
        }


        private CalendarAccessControlContext()
        {
        }
    }

이러니깐!!! new 를 통해 객체를 못만듭니다. 왜냐고물으신다면 추상클래스는 new를 통해 객체를 생성할수없습니다.

왜냐고물으신다면 그렇게 정외가 되어있습니다.

두번째로 그렇다면 어떻게 쓸수있을까요? 위에 답은 이미나와있습니다..

추상메소들 모조리 몽땅~ 다 구현해주는 겁니다...

그렇다면 그렇게 해봅시다!

어떤가요? Calendar를 new 를 통해 객체생성이됩니다..

다만 좀 구현해줄께 많을 뿐이죠

아니 그렇다면...

public class TestInterface {

    public static void main(String[] args) {
//        Calendar cal =Calendar.getInstance();
      
           
        Calendar cal = new Calendar() {
           
            @Override
            public void roll(int i, boolean flag) {
                // TODO Auto-generated method stub
               
            }
           
            @Override
            public int getMinimum(int i) {
                // TODO Auto-generated method stub
                return 0;
            }
           
            @Override
            public int getMaximum(int i) {
                // TODO Auto-generated method stub
                return 0;
            }
           
            @Override
            public int getLeastMaximum(int i) {
                // TODO Auto-generated method stub
                return 0;
            }
           
            @Override
            public int getGreatestMinimum(int i) {
                // TODO Auto-generated method stub
                return 0;
            }
           
            @Override
            protected void computeTime() {
                // TODO Auto-generated method stub
               
            }
           
            @Override
            protected void computeFields() {
                // TODO Auto-generated method stub
               
            }
           
            @Override
            public void add(int i, int j) {
                // TODO Auto-generated method stub
               
            }
        };

    }

}

이렇게 많이 구현해주는데 시간이 많이 걸리는데..

왜 굳이 추상클래스를 사용하느냐라고 궁금할수있습니다

그런데.. 이렇게 대부분의 블로그들에서 공통된 오류가 있습니다...

추상클래스를 사용하기위해서는 abstract로 구현된 메소드를 오버라이딩해서 써야된다고하는데 사실 다른방법이 있습니다

import java.util.Calendar;

public class TestInterface {

    public static void main(String[] args) {


        Calendar cal = Calendar.getInstance();

    }

}  
이것입니다 getInstance()메소드가 무엇이길래 그러느냐..

그렇다면 봅시다!

    public static Calendar getInstance()

    {
        Calendar calendar = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault());
        calendar.sharedZone = true;
        return calendar;
    }

먼진몰라도(여기서 캡슐화의 특징이 나옵니다. 안에있는 로직이 어떻게 돌아가는지몰라도 이메소드를 쓰면 어떤결과가 나오겠구나.. 하는 아~주 좋은 점이죠)

) calendar를 생성해줍니다.

static이라는 것은 new의 선언 없이 객체를 생성할수 있게끔 해줍니다.getInstance메소드를 통해서요!

그렇다면 여기서 잠깐 추상클래스와 추상메소드를 정리해보면

추상클래스는 extends 를 통해 쓸수있는데 쓰기위해서는 오버라이딩 해줘야한다. 그렇지만 static과 적절한 메소드를 통해 오버라이딩을 해주지 않아도 쓸수있다.

 추상메소드란 추상클래스안에있는 것인데 {}와 {}안에 내용이 없는 메소드이다.

 그렇다면 이제 마지막으로 인터페이스란 무엇이냐

public abstract class Calendar    
    implements Serializable, Cloneable, Comparable  //이부분의 인터페이스를 살펴보겠습니다
{
    private static class CalendarAccessControlContext
    {

        private static final AccessControlContext INSTANCE;

        static
        {
            RuntimePermission runtimepermission = new RuntimePermission("accessClassInPackage.sun.util.calendar");
            PermissionCollection permissioncollection = runtimepermission.newPermissionCollection();
            permissioncollection.add(runtimepermission);
            INSTANCE = new AccessControlContext(new ProtectionDomain[] {
                new ProtectionDomain(null, permissioncollection)
            });
        }


        private CalendarAccessControlContext()
        {
        }
    }

 

package java.io;


public interface Serializable
{
}

 

package java.lang;

// Referenced classes of package java.lang:
//            Object

public interface Cloneable
{
}


package java.lang;

// Referenced classes of package java.lang:
//            Object

public interface Comparable
{

    public abstract int compareTo(Object obj);
}

어떻습니까? 한번 보는것이 여러번 설명하는것보다 눈에 잘들어오죠...

인터페이스를 정의하는데 순수하게 뼈대만을 설계하고 있습니다. 가장 기본적인 뼈대죠..

이보다 완벽한 예제는 없는것 같습니다.(제가 만든 예제는 아니고.. 기업에서 만든것이죠...)

제가 설명해드리고 싶었던것은 나무를 보는 것보다 숲을 보는 것이 이해가 빠른것같네요...

저도 사실 interface가 뭔지 추상클래스가 뭔지 이 글을 쓰기전에는 10의 1정도만 알고있었습니다.

어찌됫든 디컴파일러의 위력을 다시한번 느낄수있는 글인였던것같습니다


출처 http://seodh007.tistory.com/23

반응형

'Java기초' 카테고리의 다른 글

replace replaceAll 차이  (0) 2014.08.01
java stack trace  (0) 2014.05.09
JVM 메모리  (0) 2014.04.30
정규식 특수문자  (0) 2013.07.15
인터페이스 추상클래스  (0) 2013.07.11

+ Recent posts