Ace-T's Blog 내 검색 [네이버 커넥트 이웃 합니다~^-^/ 요청 大 환영~~]

메시지큐에 대해 알아보자.

Architecture/AA 2017.06.27 14:30
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T
모델 종류 
  • 발행/구독(publish - and - subscribe) 모델
          1: 다 - 모든 클라이언트에게 모든 메시지의 사본을 전달.
           publisher -> topic -> subscriber
                                         -> subscriber
                                         -> subscriber


  • 지점간 연결(point -  to - point) 모델 
          1:1 - 하나의 메시지는 하나의 클라이언트에만 전송(큐는 공유 가능)
          sender -> queue -> receiver 

위의 모델 중에 publish - and - subscribe(pub - sub) 모델에 대해서 알아보자!

pub/sub 구조
보통의 message queue들은 publisher - message broker(topic) - subscriber 구조를 사용한다.
publisher(message data)를 하면 가운데 있는 message broker가 메시지를 선택하고 처리하는 즉, 내부적으로 구독하고 있는
subscriber들을 찾아서 메시지를 보낸다. 

opensource message queue중에 nats라는 녀석이 있다. (http://nats.io/)
lib는 https://github.com/nats-io/go-nats 참고!


pub/sub 구현(w/go lang)
그러면 pub/sub 모델을 구현한다고 생각해보자.
우선은 메시지큐 server가 필요하겠다. 그리고 그 서버를 붙는 client도 필요하다.
보통 jms, nats, amazon sqs 등등이 서버가 되겠다. client는 제공되어지는 publish()등의 함수가 있는 lib 정도.

ex)  메시지 큐 동작 과정
  1. 클라이언트가 NATS 서버와의 TCP / IP 소켓 연결을 설정.
    1. nc, _ := nats.Connect(nats.DefaultURL)
  2. 발행
    1. nc.Publish("foo", []byte("Hello World"))
  3. 구독 (subject가 구독대상 : foo)
          // Simple Async Subscriber
    nc.Subscribe("foo", func(m *nats.Msg) {
                      fmt.Printf("Received a message: %s\n", string(m.Data))
     })

    // Simple Sync Subscriber
    sub, err := nc.SubscribeSync("foo")
    m, err := sub.NextMsg(timeout)
  1. 구독 해제(Sync Subscriber 일 경우에만)
    // Unsubscribe
          sub.Unsubscribe()    
     5. defer nc.Close()    

func TestNatsWorking(t *testing.T) {
   nc, _ := nats.Connect(nats.DefaultURL)
   defer nc.Close()
   // Simple Publisher
   nc.Publish("foo", []byte("Hello World"))

   // Simple Async Subscriber
   nc.Subscribe("foo", func(m *nats.Msg) {
      fmt.Printf("Received a message: %s\n", string(m.Data))
   })

}



           


저작자 표시 비영리 변경 금지
신고

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

PlaybackController Interface

Architecture/A.I 2017.05.26 15:06
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

그림은 무관합니다. 최강두산 화이팅! ㅋㅋ





Overview

PlaybackController 인터페이스는 음성 요청이 아닌 클라이언트 측 버튼 누르기 또는 GUI 어바이어를 통해 
재생 대기열을 탐색하기위한 일련의 이벤트를 제공합니다.

PlayCommandIssued Event 

PlayCommandIssued 이벤트는 사용자가 클라이언트상의 버튼 누름 또는 GUI affordance를 사용하여 미디어 항목의 재생을 시작 / 재개 할 때 전송되어야합니다.

Sample Message

{
    "context": [
        {{Alerts.AlertsState}},
        {{AudioPlayer.PlaybackState}},
        {{Speaker.VolumeState}},
        {{SpeechSynthesizer.SpeechState}}
        {{SpeechRecognizer.RecognizerState}}
    ],
    "event": {
        "header": {
            "namespace": "PlaybackController",
            "name": "PlayCommandIssued",
            "messageId": "{{STRING}}"
        },
        "payload": {
        }
    }
}


Context
PlayCommandIssued 이벤트는 클라이언트가 모든 클라이언트 구성 요소 상태의 상태를 보내도록 요구합니다. 
추가 정보는 컨텍스트를 참조하십시오.

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters
빈 payload를 보내야합니다.


PauseCommandIssued Event 

PauseCommandIssued 이벤트는 사용자가 클라이언트상의 단추 누르기 또는 GUI affordance를 사용하여 미디어 항목의 재생을 일시 중지 할 때 전송되어야합니다.

Sample Message

{
    "context": [
        {{Alerts.AlertsState}},
        {{AudioPlayer.PlaybackState}},
        {{Speaker.VolumeState}},
        {{SpeechSynthesizer.SpeechState}}
        {{SpeechRecognizer.RecognizerState}}
    ],
    "event": {
        "header": {
            "namespace": "PlaybackController",
            "name": "PauseCommandIssued",
            "messageId": "{{STRING}}"
        },
        "payload": {
        }
    }
}

Context
PauseCommandIssued 이벤트는 클라이언트가 모든 클라이언트 구성 요소 상태의 상태를 보내도록 요구합니다. 
추가 정보는 컨텍스트를 참조하십시오.


Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters
빈 payload를 보내야합니다.


NextCommandIssued Event 

NextCommandIssued 이벤트는 사용자가 클라이언트상의 단추 누르기 또는 GUI affordance를 사용하여 재생 대기열의 다음 미디어 항목으로 건너 뛸 때 전송되어야합니다.

Sample Message

{
    "context": [
        {{Alerts.AlertsState}},
        {{AudioPlayer.PlaybackState}},
        {{Speaker.VolumeState}},
        {{SpeechSynthesizer.SpeechState}}
        {{SpeechRecognizer.RecognizerState}}
    ],
    "event": {
        "header": {
            "namespace": "PlaybackController",
            "name": "NextCommandIssued",
            "messageId": "{{STRING}}"
        },
        "payload": {
        }
    }
}

Context
NextCommandIssued 이벤트는 클라이언트가 모든 클라이언트 구성 요소 상태의 상태를 보내도록 요구합니다. 
추가 정보는 컨텍스트를 참조하십시오.

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters
빈 payload를 보내야합니다.


PreviousCommandIssued Event 

클라이언트가 버튼 누름 또는 GUI affordance를 사용하여 재생 대기열에서 이전 미디어 항목으로 건너 뛸 때 PreviousCommandIssued 이벤트를 보내야합니다.

Sample Message

{
    "context": [
        {{Alerts.AlertsState}},
        {{AudioPlayer.PlaybackState}},
        {{Speaker.VolumeState}},
        {{SpeechSynthesizer.SpeechState}}
        {{SpeechRecognizer.RecognizerState}}
    ],
    "event": {
        "header": {
            "namespace": "PlaybackController",
            "name": "PreviousCommandIssued",
            "messageId": "{{STRING}}"
        },
        "payload": {
        }
    }
}

Context

PreviousCommandIssued 이벤트는 클라이언트가 모든 클라이언트 구성 요소 상태의 상태를 보내도록 요구합니다. 
추가 정보는 컨텍스트를 참조하십시오.

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters
빈 payload를 보내야합니다.



저작자 표시 비영리 변경 금지
신고

'Architecture > A.I' 카테고리의 다른 글

PlaybackController Interface  (0) 2017.05.26
Understanding Alerts  (0) 2017.05.26
Alerts Interface  (0) 2017.05.25
AudioPlayer Interface  (0) 2017.05.24

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

Understanding Alerts

Architecture/A.I 2017.05.26 15:03
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

Overview

alerts에 관해서, 사용자는 일반적으로 타이머 설정, alert 설정 또는 타이머 또는 alert 삭제 / 취소의 세 가지 방법 중 하나로 Alexa 사용 가능 제품과 상호 작용합니다. 사용자가 타이머 또는 알람을 설정하려면 제품에 활성 인터넷 연결이 있어야합니다
이 작업은 제품에 조치 (예 : SetAlert 및 DeleteAlert)를 지시하고 Alexa Voice Service (AVS)에 조치가 취해 졌음을 알리는 이벤트
 (예 : SetAlertSucceeded 및 DeleteAlertSucceeded)를 전송하는 데 필요합니다.

인터넷 연결이 끊어지면 제품에 이전에 설정된 타이머 또는 alert을 처리 할 수 있어야합니다. 
예를 들어, 사용자가 오전 7시 30 분에 알람을 설정하면 잠자기 전에 제품이 밤 사이에 인터넷 연결이 끊어지면 제품에 오전 7시 30 분에 알림을 재생할 수있는 기능이 있어야합니다. 인터넷 연결이 끊어진 후 타이머 및 알람을 실행하면 긍정적인 사용자 환경이 보장됩니다.

제품의 시계를 관리하는 것은 타이머와 alert이 설계된대로 작동하도록하는 데 중요합니다. 
AVS에서 보낸 모든 directive는 UTC 시간에 반환됩니다. 사용자가 제품에 "3 분 동안 타이머 설정"을 지시하면 AVS는 해당 사용자의 시간대를 고려하여 요청에 해당하는 올바른 UTC 시간을 결정합니다. 제품의 시간이 현지에서 조정 된 경우 타이머 및 알람이 제대로 작동하지 않을 수 있습니다. 이러한 이유로 아마존은 시계 동기화에 NTP (Network Time Protocol)를 사용하도록 제안합니다.

정전 또는 재부팅이 필요한 경우 제품에 alert을 유지하고 복원 할 수 있어야합니다. 
향후 alert가 예정된 경우 제품에서 alert을 로컬로 설정해야합니다.
 귀하의 제품은 alert가 다시 설정되었음을 Alexa에 알리는 이벤트를 전송할 필요가 없습니다
alert가 해제 될 때 제품 전원이 꺼지거나 재부팅되는 경우 다음 규칙을 따라야합니다.
  • 지난 30 분 내에 alert가 예정된 경우 제품에서 alert를 트리거하고 모든 해당 이벤트를 보내야합니다.
  • alert가 예정된 수행에서 30 분 이상 경과하면 이를 폐기해야하며 제품은 각 폐기 alert에 대해 AVS에 AlertStopped 이벤트를 보내야합니다.

Alexa 기반 제품은 다음과 같이 요약 할 수 있습니다.
  • 인터넷 연결이 끊어지면 이전에 설정된 alert를 처리 할 수 있어야합니다.
  • 네트워크 시간 프로토콜을 사용하여 제품의 시계를 관리하십시오.
  • 제품의 전원이 꺼 지거나 재부팅되는 경우 이전에 설정된 alert를 처리 할 수 있어야합니다.

다음 예제는 타이머 및 알람이 AVS와 함께 작동하는 방법을 이해하는 데 사용해야합니다. 
이러한 시나리오는 다음을 가정합니다.
  • 귀하의 제품은 사용자의 말을 처리하고 AVS로부터받은 지침에 따라 행동하도록 고안되었습니다.
  • 귀하의 제품은 클라우드 기반 지시문을 수신하는 다운 채널을 구축했습니다. 
          자세한 내용은 AVS를 사용하여 HTTP / 2 연결 관리를 참조하십시오.
  • 이벤트가 발생하면 제품에서 AVS를 업데이트합니다.
  • 모든 이벤트는 개별 이벤트 스트림으로 전송됩니다.

Scenario 1: Set a Timer with Voice

사용자가 5 분 동안 타이머를 설정하려고합니다. 
사용자가 "5 분 동안 타이머 설정"이라고 말하면 제품은 사용자의 음성을 캡처하고 AVS에 인식 이벤트를 전송해야합니다. 
그런 다음 AVS는 제품에 수행 할 작업을 지시하는 일련의 directive로 응답하고 제품은 조치를 취해야합니다. 
익숙한 것 같습니다. 타이머나 alert을 설정하는 것은 제품과 AVS 간의 표준 상호 작용 모델을 따르기 때문입니다. 
질문을하거나 요청을하고 응답을 받고 그에 따라 행동하고 AVS에 문제가 발생했음을 업데이트하십시오.

이것은 타이머를 설정할 때의 메시지 흐름입니다.
  • 사용자가 타이머 설정을 요청하면 AVS는 Speak Directive를 보내 제품에 연결된 오디오를 재생하도록 지시합니다. 
     이 시나리오에서는 "5 분, 지금 시작하십시오."알렉사 speech의 재생이 시작되면 제품에서 AVS로 SpeechStarted 이벤트를 보내야합니다.
  • Alexa speech의 재생이 완료되면 SpeechFinished 이벤트를 AVS에 보내야합니다.
  • 또한 AVS는 다운 채널 스트림에서 제품에 SetAlert 지정 문을 전송합니다. 제품 타이머는 5 분 동안 설정되어야하며 SetAlertSucceeded 이벤트는 AVS로 전송되어야합니다. 제품에는 타이머 설정 및 타이머 만료에 필요한 논리가 있어야합니다.
  • 5 분이 경과 한 후 제품은 타이머가 만료되었음을 사용자에게 알리고 AlertStarted 이벤트를 AVS로 보내야합니다.


사용자는 음성 또는 Amazon Alexa 앱을 사용하여 타이머를 중지 할 수 있어야하며 가능한 경우 물리적 컨트롤 (버튼 또는 GUI)을 통해 타이머를 중지 할 수 있어야합니다.
  • 요청이 음성 또는 Amazon Alexa 앱을 통해 이루어지면 AVS는 제품에 DeleteAlert Directive를 보냅니다. 이 때 제품은 AlertStopped 이벤트와 DeleteAlertSucceeded 이벤트를 AVS에 보내야 합니다.
  • button affordance 결과로 타이머가 중지되면 제품은 AlertStopped 이벤트를 AVS로 전송해야합니다.

올바르게 구현 된 경우 타이머가 제품에 설정되면 인터넷 연결없이 작동해야합니다. 
그러나 이벤트가 발생했음을 AVS에 알리는 연결이 필요합니다. 
따라서 인터넷 연결이 다시 설정되면 제품 상태에서 AVS를 업데이트하는 데 필요한 논리가 제품에 있어야합니다.

아래의 시퀀스 다이어그램은 타이머가 설정된 경우 제품과 AVS 간의 예상되는 상호 작용을 보여줍니다.







Scenario 2: Cancel an Alarm Using the Amazon Alexa App

이 시나리오에서는 alert가 성공적으로 설정되었고 사용자가 해당 alert를 취소하려고한다고 가정해야합니다.
사용자는 Amazon Alexa 앱을 열어 모든 제품 별 알람 (활성 및 비활성)에 액세스 할 수 있습니다. 
사용자는 알람으로 이동하고 오전 7시 30 분에 설정된 알람을 취소합니다.

DeleteAlert directive는 다운채널 스트림으로 제품으로 전송됩니다. 지금까지 모든 사용자 조치가 Amazon Alexa 앱에서 발생했습니다.
DeleteAlert directvie를 받으면 제품에서 directive에 따라 행동하고 오전 7시 30 분에 설정된 경보를 취소 할 수 있어야합니다. 
여기에는 알람이 삭제 된 후 AVS에 DeleteAlertSucceeded 이벤트를 보내는 작업이 포함됩니다.

이 시퀀스 다이어그램은 Amazon Alexa 앱을 사용하여 알람을 취소 한 경우 제품과 AVS 간의 예상되는 상호 작용을 보여줍니다.




Scenario 3: Set a Recurring(순환하는) Alarm

제품에 반복적인 알람을 설정하는 과정은 타이머 설정과 유사합니다. 
directive와 event의 흐름은 거의 동일합니다 (시나리오 1 참조). 
유일한 차이점은 반복 알람이 취소 될 때까지 AVS가 매일 새 SetAlert directive를 제품에 보냅니다.
이 시퀀스 다이어그램은 반복 알람이 설정 될 때 제품과 AVS 간의 예상되는 상호 작용을 보여줍니다.





Scenario 4: Snooze a Sounding Alarm

이 시나리오에서는 alert가 성공적으로 설정되었고 현재 소리가 나는 것으로 가정해야합니다.
중요 : 다시 알림은 음성으로 만 시작할 수 있습니다.

알람이 울리고 사용자가 "Alexa, snooze"라고 말하면 몇 가지 일이 발생합니다. 
사용자 음성이 AVS로 스트리밍되고 업데이트 된 예약 시간이있는 새 SetAlert directive가 제품으로 전송됩니다. 
귀하의 제품은 울리는 alert의 토큰과 새로운 SetAlert directive가 일치하는지 확인해야합니다. 
토큰이 일치하면 제품에서 경고음을 취소하고 SetAlert directive의  payload에 포함 된 scheduledTime에 대한 새 알람을 설정해야합니다.
이 시퀀스 다이어그램은 알람이 일시 중지 된 경우 제품과 AVS 간의 예상되는 상호 작용을 보여줍니다.




Lifecycle Events

이 표는 제품이 AVS에 보내야하는 네 가지 사용자 조치 및 라이프 사이클 이벤트를 제공합니다.

참고 : DeleteAlertSucceeded 또는 DeleteAlertFailed는 DeleteAlert directive에 대한 응답으로만 전송됩니다. 
로컬로 수행 된 작업에 대해 이러한 이벤트를 보내지 마십시오.


User Action
Server Behavior
Alert is Active (Making Noise)
Send AlertStarted
Send AlertStopped
Send DeleteAlertSucceeded / DeleteAlertFailed
User says: “Stop Alert.”
DeleteAlert를downchannel stream에서 전송.
Y
Y
Y
Y
사용자는 실제 컨트롤 (버튼 또는 GUI)을 사용하여 활성 alert를 로컬에서 중지합니다.
None
Y
Y
Y
N
사용자가 음성 요청 또는 Amazon Alexa 앱을 통해 비활성 알림을 취소합니다.
DeleteAlertdiretive 를 downchannel stream에서 전송.
N
N
N
Y
재생하지 않고 알람이 만료되었습니다 
(예 : 예정된 이행 시간에 기기의 전원이 켜지지 않음)
None
N
N
Y
N


참고 : https://developer.amazon.com/public/solutions/alexa/alexa-voice-service/reference/timers-and-alarms-conceptual-overview#overview







저작자 표시 비영리 변경 금지
신고

'Architecture > A.I' 카테고리의 다른 글

PlaybackController Interface  (0) 2017.05.26
Understanding Alerts  (0) 2017.05.26
Alerts Interface  (0) 2017.05.25
AudioPlayer Interface  (0) 2017.05.24

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

Alerts Interface

Architecture/A.I 2017.05.25 17:49
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T


Overview

Alert 인터페이스는 타이머와 알람을 설정, 관리 및 취소하는 데 사용되는 directive와  event를 제공합니다. 
AVS는 타이머와 알람을 설정하고 관리하기 위해 고객에게 지시를 보내지만 궁극적으로 인터넷 연결이 끊어 지거나 제품 내 시계가 NTP와 동기화되지 않으면 타이머와 알람을 관리하는 데 필요한 논리를 구현해야합니다. 
자세한 구현 세부 정보는 Understanding Alerts (Alerts 이해) 및 Interaction Model (상호 작용 모델)을 참조하십시오.

이 문서는 다음 주제를 다룹니다.
  • Alerts State Diagram
  • Alerts Directives and Events

State Diagram

다음 다이어그램은 Alerts 구성 요소에 의해 구동되는 상태 변경을 보여줍니다. 
Boxes는 Alerts 상태를 나타내고 connectors는 전환을 나타냅니다.

Alerts은 다음 상태를 지원합니다.
IDLE : 이전에 설정된 Alerts이 울리기 전에 Alerts 구성 요소가 IDLE 상태 여야합니다. 
alerts가 중지 / 완료되면 Alerts도 IDLE 상태로 되돌아 가야합니다. 
이것은 사용자 음성, 실제 버튼 누름 또는 GUI affordance의 결과로 발생할 수 있습니다.

FOREGROUND ALERT : 클라이언트 측 alert이 이미 설정되었다고 가정하면 alerts가 시작되고 AlertStarted 이벤트가 Alexa Voice Service로 전송되면 alerts는 IDLE 상태에서 alert foreground 상태로 전환해야합니다.

alerts 채널이 foreground에 있는 경우에만 해당되며 Dialog channel이 비활성 상태임을 나타냅니다. 
채널 및 채널 우선 순위에 대한 자세한 내용은 상호 작용 모델을 참조하십시오.

음성, 버튼 누름 또는 GUI 기능을 통해 Alerts가 중지되면 Alerts 구성 요소가 alert foreground 상태에서 IDLE 상태로 전환됩니다.
alerts가 울리는 동안 Dialog channel이 활성화되면 Dialog channel이 활성화되어있는 한 alerts 구성 요소는  foreground alerts 상태에서 background alert 상태로 전환해야합니다. Dialog channel이 비활성 상태가 되면 중지/완료 될 때까지 foreground alert상태로 되돌아 가야합니다.

BACKGROUND ALERT : Dialog channel이 활성화되면 Alerts 구성 요소는 background alert 상태로 전환해야합니다. 
채널 및 채널 우선 순위에 대한 자세한 내용은 상호 작용 모델을 참조하십시오.




SetAlert Directive

이 directive는 AVS에서 보내 지정된 시간이나 시간 동안 타이머 또는 알람을 설정하도록 클라이언트에 지시합니다. 
타이머 또는 알람을 설정하기위한 음성 요청 또는 Amazon Alexa 앱을 사용하여 이전에 설정된 알람을 다시 사용할 수있게 설정 한 
경우 클라이언트가 SetAlert Directive를 수신 할 수 있습니다.

Sample Message

{
    "directive": {
        "header": {
            "namespace": "Alerts",
            "name": "SetAlert",
            "messageId": "{{STRING}}",
            "dialogRequestId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "type": "{{STRING}}",
            "scheduledTime": "{{STRING}}"
        }
    }
}


Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string
dialogRequestId
A unique ID used to correlate directives sent in response to a specific Recognize event.

Note: dialogRequestId is only sent in response to a speech request. dialogRequestId is not included in directives sent to your client on the downchannel stream.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token that uniquely identifies the alert.
string
type
Identifies whether the alert is a timer or alarm. 
Accepted values: TIMER or ALARM.
string
scheduledTime
The scheduled time for an alert in ISO 8601 format.
string


SetAlertSucceeded Event

SetAlertSucceeded 이벤트는 SetAlert Directive를받은 후 클라이언트가 경고를 성공적으로 설정할 때  AVS로 보내야합니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "Alerts",
            "name": "SetAlertSucceeded",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}"
        }
    }
}


Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the SetAlert directive.
string



SetAlertFailed Event

SetAlertFailed 이벤트는 SetAlert Directive를받은 후 클라이언트가 alert를 설정하지 못한 경우 AVS로 보내야합니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "Alerts",
            "name": "SetAlertFailed",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}"
        }
    }
}


Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the SetAlert directive.
string


DeleteAlert Directive

이 Directive는 AVS에서 전송되어 클라이언트에게 특정 기간 또는 시간 동안 기존 타이머 또는 alert를 삭제하도록 지시합니다. 
클라이언트는 타이머 또는 알람을 취소/삭제할 음성 요청 또는 미리 설정된 alert가 Amazon Alexa 앱에서 삭제 된 경우 DeleteAlert Directive를 수신 할 수 있습니다.

Sample Message

{
    "directive": {
        "header": {
            "namespace": "Alerts",
            "name": "DeleteAlert",
            "messageId": "{{STRING}}",
            "dialogRequestId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string
dialogRequestId
A unique ID used to correlate directives sent in response to a specific Recognize event.

Note: dialogRequestId is only sent in response to a speech request. dialogRequestId is not included in directives sent to your client on the downchannel stream.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token that uniquely identifies the alert.
string

DeleteAlertSucceeded Event

DeleteAlertSucceeded 이벤트는 클라이언트가 기존 alert를 성공적으로 삭제하거나 취소 할 때 DeleteAlert Directive를 받은 후 AVS로 전송되어야합니다.
Note: For more information on when to send the DeleteAlertSucceeded event, please see Understanding Alerts.

Sample Message

{
    "event": {
        "header": {
            "namespace": "Alerts",
            "name": "DeleteAlertSucceeded",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the DeleteAlert directive.
string


DeleteAlertFailed Event

DeleteAlertFailed 이벤트는 클라이언트가 기존 alert를 삭제하거나 취소하지 못하는 DeleteAlert Directive를 수신 한 후 AVS로 보내야합니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "Alerts",
            "name": "DeleteAlertFailed",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the DeleteAlert directive.
string


AlertStarted Event

alert이 예정된 시간에 트리거되면 AlertStarted 이벤트를 AVS로 전송해야합니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "Alerts",
            "name": "AlertStarted",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the SetAlert directive.
string


AlertStopped Event

활성 alert가 중지되면 AlertStopped 이벤트를 AVS로 전송해야합니다. 
다음 두 가지 방법 중 하나로 alert를 중지 할 수 있습니다.

1. DeleteAlert Directive를 수신했습니다. AlertStopped 이벤트를 보낸 후에 클라이언트는 DeleteAlertSucceeded 이벤트 또는 DeleteAlertFailed 이벤트로 경고가 성공적으로 삭제 된 경우 AVS에 알려야합니다. 
    이 상호 작용은 alert 이해에 설명되어 있습니다. 
2. 물리적 컨트롤 (하드웨어 버튼 또는 GUI).

Sample Message

{
    "event": {
        "header": {
            "namespace": "Alerts",
            "name": "AlertStopped",
            "messageId": "{STRING}"
        },
        "payload": {
            "token": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the SetAlert directive.
string


AlertEnteredForeground Event

AlertEnteredForeground 이벤트는 활성 alert가 foreground로 들어가거나 (전체 볼륨으로 재생 될 때) 클라이언트에서 AVS로 전송되어야하며, Dialog channel의 동시 대화가 완료된 후 foreground로 다시 입력되어야합니다. 
채널 상호 작용에 대한 자세한 내용은 상호 작용 모델을 참조하십시오.

Sample Message

{
    "event": {
        "header": {
            "namespace": "Alerts",
            "name": "AlertEnteredForeground",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the SetAlert directive.
string


AlertEnteredBackground Event

Dialog 채널에서의 동시 상호 작용이 발생하는 동안 활성 alert가 foreground에서 나올 때 (감쇠 또는 일시 정지) AlertEnteredBackground 이벤트를 클라이언트에서 AVS로 보내야합니다. 
채널 상호 작용에 대한 자세한 내용은 상호 작용 모델을 참조하십시오.

Sample Message

{
    "event": {
        "header": {
            "namespace": "Alerts",
            "name": "AlertEnteredBackground",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided in the SetAlert directive.
string








저작자 표시 비영리 변경 금지
신고

'Architecture > A.I' 카테고리의 다른 글

PlaybackController Interface  (0) 2017.05.26
Understanding Alerts  (0) 2017.05.26
Alerts Interface  (0) 2017.05.25
AudioPlayer Interface  (0) 2017.05.24

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

AudioPlayer Interface

Architecture/A.I 2017.05.24 16:25
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

Overview
AudioPlayer 인터페이스는 음성을 통해 오디오 재생을 제어하는 directive와 재생 진행을 관리하고 모니터링하는 event를 제공합니다. 
재생 컨트롤을 버튼 (물리적 또는 GUI)에 매핑하려는 경우 PlaybackController 인터페이스를 참조.
이 페이지는 다음과 같은 주제를 다룹니다.
  •   AudioPlayer State Diagram
  •   AudioPlayer directive 및 event

State Diagram
상태 다이어그램 다음 다이어그램은 AudioPlayer 구성 요소에 의해 구동되는 상태 변경을 보여줍니다. 
Boxes는 AudioPlayer 상태를 나타내며 Connectors는 상태 전환을 나타냅니다.








AudioPlayer의 상태는 다음과 같습니다.
IDLE : AudioPlayer는 제품의 전원을 처음 켜거나 재부팅 한 후 Play directive를 사용하기 전에 IDLE 상태에 있습니다.
PLAYING : 클라이언트가 오디오 스트림 재생을 시작하면 AudioPlayer는 IDLE 상태에서 PLAYING 상태로 전환해야합니다.
오디오 스트림 일시 중지 또는 중지, 클라이언트가 스트림 버퍼링에 문제가 있거나 재생에 실패한 경우 클라이언트에서 작업 수행을 지시하는 지시문을 받으면 작업이 수행 될 때 AudioPlayer가 적절한 상태로 전환되어야합니다. AVS에 이벤트 보내기). 그렇지 않으면 현재 스트림이 끝날 때까지 AudioPlayer가 재생 상태를 유지해야합니다.
또한 AudioPlayer는 다음과 같은 경우 재생 상태를 유지해야합니다.
  • AVS로 재생(playback) 진행보고
  • AVS에 stream metadata 보내기

STOPPED : AudioPlayer가 중지 된 상태로 전환해야하는 경우가 4 가지입니다. 
재생 상태에있는 동안 AudioPlayer는 다음과 같은 경우에 중지 상태로 전환해야합니다. 
1) 스트림에 문제가 발생하여 재생에 실패한 경우.
2) 클라이언트는 AVS로부터 Stop directive를 받을 경우. 
3) clearBehavior가 CLEAR_ALL 인 ClearQueue directive을 받을 경우. 
4) REPLACE_ALL의 playBehavior가있는 Play directive을 받을 경우.
paused 또는 buffer_underrun 상태에서 CLEAR_ALL에 대한 ClearQueue directive를 수신하면 AudioPlayer는 중지로 전환 해야함. AudioPlayer는 클라이언트가 Play directive를 받고 오디오 스트림 재생을 시작하고 AVS에 PlaybackStarted 이벤트를 보낼 때마다 중지에서 재생으로 전환해야합니다.

PAUSED : 우선 순위가 높은 입력 / 출력 (예 : 사용자 또는 Alexa 음성)을 수용하기 위해 콘텐츠 채널의 오디오가 일시 중지 된 경우 AudioPlayer가 일시 중지 상태로 전환해야합니다. 우선 순위가 지정된 작업이 완료되면 재생을 다시 시작해야합니다. 
오디오 입 / 출력의 우선 순위 지정에 대한 자세한 내용은 상호 작용 모델을 참조하십시오.

BUFFER_UNDERRUN : 클라이언트가 읽히는 것보다 느리게 데이터를 제공받을 때, AudioPlayer는 buffer_underrun 상태로 전환해야합니다. 
AudioPlayer는 버퍼가 재생을 다시 시작할 정도로 충분히 찰 때까지이 상태를 유지해야하며, 이 시점에서 재생 상태로 돌아와야합니다.

FINISHED : 스트림 재생이 끝나면 AudioPlayer가 완료 상태로 전환해야합니다. 이것은 재생 대기열의 모든 스트림에 해당됩니다. 
재생 대기열이 대기중인 경우에도 클라이언트는 AVS에 PlaybackFinished event를 보내야하며, 이후에 각 스트림의 재생이 끝나면 재생 상태에서 종료되도록 완료해야합니다.

AudioPlayer는 다음과 같은 경우 완료에서 재생으로 전환해야합니다.
  • 클라이언트는 Play directive를 받습니다.
  • 재생 대기열의 next stream이 재생을 시작합니다 (PlaybackStarted event 다음).



Play Directive
Play directive는 클라이언트로 보내 오디오 재생을 시작합니다. 
JSON directive와 최대 하나의 오디오 스트림 또는 바이너리 오디오 첨부 파일로 구성된 멀티 파트 메시지입니다.

directive의 payload에 포함 된 playBehavior 매개 변수를 사용하여 클라이언트가 스트림의 대기열 처리 및 재생을 처리하는 방법을 결정할 수 있습니다. 
허용 된 값은 취해야 할 조치에 대한 힌트를 제공합니다.
REPLACE_ALL :  Play 지시어로 반환 된 스트림의 재생을 즉시 시작하고 현재 스트림과 대기열에 포함 된 스트림을 바꿉니다. 
                             스트림이 재생 중이고 REPLACE_ALL의 playBehavior로 Play 지시문을 받으면 AVS에 PlaybackStopped 이벤트를     
                             보내야합니다.
ENQUEUE : 스트림을 현재 큐 끝에 추가합니다.
REPLACE_ENQUEUED : 대기열의 모든 스트림을 바꿉니다. 현재 재생중인 스트림에는 영향을주지 않습니다.

NOTE.
재생 대기열에 스트림을 추가 할 때 활성 스트림의 토큰이 대기열에 추가되는 스트림의 expectedPreviousToken과 일치하는지 확인해야합니다. 토큰이 일치하지 않으면 스트림을 무시해야합니다. 그러나 expectedPreviousToken이 반환되지 않으면 스트림을 큐에 추가해야합니다.


Sample Message

{
    "directive": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "Play",
            "messageId": "{{STRING}}",
            "dialogRequestId": "{{STRING}}"
        },
        "payload": {
            "playBehavior": "{{STRING}}",
            "audioItem": {
                "audioItemId": "{{STRING}}",
                "stream": {
                        "url": "{{STRING}}",
                        "streamFormat" "AUDIO_MPEG"
                        "offsetInMilliseconds": {{LONG}},
                        "expiryTime": "{{STRING}}",
                        "progressReport": {
                            "progressReportDelayInMilliseconds": {{LONG}},
                            "progressReportIntervalInMilliseconds": {{LONG}}
                        },
                        "token": "{{STRING}}",
                        "expectedPreviousToken": "{{STRING}}"
                }
            }
        }
    }
}


Binary Audio Attachment
Play directive에는 멀티 파트 메시지의 일부로 해당 이진 오디오 첨부 파일이있을 수 있습니다. 
바이너리 오디오 첨부 파일이 있으면 url에 제공된 값에 다음 접두사 cid가 포함됩니다.

다음 멀티 파트 헤더가 바이너리 오디오 첨부 파일 앞에옵니다.
Content-Type : application/octet-stream
Content-ID : {{Audio Item CID}}
{{BINARY AUDIO ATTACHMENT}}

Header Parameters

Parameter
Description
Type
messageId
특정 메시지를 나타내는 데 사용되는 고유 ID입니다.
string
dialogRequestId
특정 Recognize event에 응답하여 전송 된 directive를 상호 연관시키는 데 사용되는 고유 ID입니다.

Note: dialogRequestId는 음성 요청에 대한 응답으로 만 전송됩니다. dialogRequestId는 downchannel stream에서 클라이언트로 전송 된 directive에 포함되어 있지 않습니다.
string


Payload Parameters
중요 : 귀하의 클라이언트는 Play에서 지원하는 모든 payload 매개 변수를 수용하고 작동하도록 설계되어야하며 
JSON의 키 / 값 쌍이 누락 되어도 중단되어서는 안됩니다.
Parameter
Description
Type
playBehavior
재생 힌트를 제공합니다. 허용되는 값 :  REPLACE_ALL, ENQUEUE, REPLACE_ENQUEUED. 
  • REPLACE_ALLPlay Directive로 반환 된 스트림의 재생을 즉시 시작하고 현재 스트림과 대기열에 포함 된 스트림을 바꿉니다.
  • ENQUEUE현재의 큐의 마지막에 스트림을 추가합니다.
  • REPLACE_ENQUEUED큐의 모든 스트림을 바꿉니다. 현재 재생중인 스트림에는 영향을주지 않습니다.
string
audioItem
audioItem의 키 / 값 쌍을 포함합니다.
object
audioItem.audioItemId
audioItem을 식별합니다.
string
audioItem.stream
stream의 키 / 값 쌍을 포함합니다.
object
audioItem.stream.url
오디오 내용의 위치를 식별합니다. 
오디오 콘텐츠가 이진 오디오 첨부 파일 인 경우이 값은 콘텐츠의 고유 식별자이며 "cid :"와 같이 형식이 지정됩니다. 그렇지 않으면 값은 원격 http / https 위치가됩니다.
string
audioItem.stream.streamFormat
play directive에 연결된 바이너리 오디오 첨부 파일이 있으면 streamFormat이 payload에 포함됩니다. 연결된 오디오가 스트림이면이 매개 변수가 표시되지 않습니다.
Accepted Value: AUDIO_MPEG
string
audioItem.stream.offsetInMilliseconds
스트림에서 클라이언트가 재생을 시작해야하는 위치를 나타내는 타임 스탬프. 예를 들어, offsetInMilliseconds를 0으로 설정하면 스트림 재생이 0 또는 스트림 시작 부분에서 시작되어야 함을 나타냅니다. 다른 값은 재생이 제공된 오프셋에서 시작해야 함을 나타냅니다.
long
audioItem.stream.expiryTime
스트림이 유효하지 않은 경우의 ISO 8601 형식의 날짜와 시간.
string
audioItem.stream.progressReport
progress reports의 키 / 값 쌍을 포함합니다.
object
audioItem.stream.progressReport. progressReportDelayInMilliseconds
ProgressReportDelayElapsed 이벤트를 AVS로 보낼 시간 (밀리 초)을 지정합니다. ProgressReportDelayElapsed는 지정된 간격으로 한 번만 보내야합니다
참고 : 일부 음악 제공 업체는이 보고서를 요구하지 않습니다. 보고서가 필요하지 않은 경우에는 progressReportDelayInMilliseconds가 페이로드에 표시되지 않습니다.
long
audioItem.stream.progressReport. progressReportIntervalInMilliseconds
ProgressReportIntervalElapsed 이벤트를 AVS로 내보내는 시간을 밀리 초 단위로 지정합니다. ProgressReportIntervalElapsed는 지정된 간격으로 주기적으로 보내야합니다
참고 : 일부 음악 제공 업체는이 보고서를 요구하지 않습니다. 
보고서가 필요하지 않은 경우에는 progressReportIntervalInMilliseconds가 페이로드에 표시되지 않습니다.
long
audioItem.stream.token
현재의 스트림을 나타내는 opaque token 입니다.
string
audioItem.stream.
expectedPreviousToken
예상되는 이전 스트림을 나타내는 opaque token 입니다.
string


PlaybackStarted Event

클라이언트가 Play Directive를 처리하고 관련 오디오 스트림의 재생을 시작한 후에 PlaybackStarted 이벤트를 AVS로 보내야합니다.
 Note: AVS가 보내는 각 URL에 대해 하나 이상의 PlaybackStarted 이벤트가 필요합니다. 
여러 URL로 구성된 재생 목록 URL을 받으면 PlaybackStarted 이벤트를 하나만 보내십시오.

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackStarted",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": {{LONG}}
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the Play directive.
string
offsetInMilliseconds
트랙의 현재 오프셋 (밀리 초)을 나타냅니다.
long

PlaybackNearlyFinished Event

클라이언트가 재생 대기열에서 next stream을 버퍼링 / 다운로드 할 준비가되면 PlaybackNearlyFinished 이벤트를 보내야합니다. 
클라이언트는 현재 재생중인 스트림에 대한 PlaybackStarted 이벤트 이후에만 해당 이벤트가 전송되도록해야합니다. 

Alexa는 다음 중 하나를 사용하여 해당 이벤트에 응답합니다.
  • next stream을 포함하는 Play Directive
  • HTTP 204 응답 코드

Sample Message
{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackNearlyFinished",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": {{LONG}}
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the Play directive.
string
offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long


ProgressReportDelayElapsed Event

Play Directive에 progressReportDelayInMilliseconds가 있으면 ProgressReportDelayElapsed 이벤트를 AVS로 보내야합니다. 
이 이벤트는 offsetInMilliseconds가 아닌 스트림의 시작 부분에서 지정된 간격으로 한 번 보내야합니다. 
예를 들어, Play Directive에 progressReportDelayInMilliseconds 값이 20000 인 경우 ProgressReportDelayElapsed 이벤트는 
트랙 시작 부분에서 20,000 밀리 초가 지나야합니다. 그러나 Play Directive에 offsetInMilliseconds 값이 10000이고 progressReportDelayInMilliseconds 값이 20000이면 이벤트를 재생에 10,000 밀리 초씩 보내야합니다. 이는 진행 보고서가 재생 지시문의 오프셋이 아니라 스트림의 시작에서 전송되기 때문입니다

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "ProgressReportDelayElapsed",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": {{LONG}}
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the Play directive.
string
offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long


ProgressReportIntervalElapsed Event


Play Directive에 progressReportIntervalInMilliseconds가 있으면 ProgressReportIntervalElapsed 이벤트를 AVS로 보내야합니다. 
이 이벤트는 offsetInMilliseconds가 아닌 스트림의 시작부터 지정된 간격으로 정기적으로 보내야합니다. 
예를 들어 Play 지시문에 progressReportIntervalInMilliseconds 값이 20000 인 경우 ProgressReportIntervalElapsed 이벤트는 트랙 시작부터 20,000 밀리 초 및 스트림이 끝날 때까지 20,000 밀리 초마다 보내야합니다. 그러나 Play Directive에 offsetInMilliseconds 값이 10000이고 progressReportIntervalInMilliseconds 값이 20000 인 경우 재생 시작부터 10,000 밀리 초, 스트림이 끝날 때까지 20,000 밀리 초마다 이벤트를 보내야합니다. 이는 지정된 간격이 재생 지시문의 오프셋이 아니라 스트림의 시작부터 있기 때문입니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "ProgressReportIntervalElapsed",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": {{LONG}}
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the Play directive.
string
offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long


PlaybackStutterStarted Event

PlaybackStutterStarted 이벤트는 클라이언트의 AudioPlayer 구성 요소가 읽는 것보다 느린 속도로 데이터가 공급 될 때 PlaybackStarted 이벤트 다음에 AVS로 보내야합니다. 일단 이 이벤트가 보내지면 구성 요소는 buffer_underrun 상태로 전환해야하며 버퍼가 재생을 다시 시작할만큼 충분히 가득 찰 때까지이 상태를 유지합니다

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackStutterStarted",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": {{LONG}}
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the Play directive.
string
offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long

PlaybackStutterFinished Event

스트림 재생을 다시 시작할 수있을만큼 버퍼가 가득 차면 PlaybackStutterFinished 이벤트를 AVS로 보내야합니다. 
AVS는 오디오 재생이 다시 시작될 때 이후의 PlaybackStarted 이벤트를 기대하지 않습니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackStutterFinished",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": {{LONG}},
            "stutterDurationInMilliseconds": {{LONG}}
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the Play directive.
string
offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long
stutterDurationInMilliseconds
stutter의 지속 시간을 밀리 초 단위로 나타냅니다.
long

PlaybackFinished Event

클라이언트가 스트림 재생을 완료하면 PlaybackFinished 이벤트를 AVS로 전송해야합니다.
다음 경우에이 이벤트가 전송되지 않습니다.
  • 재생이 중지됩니다 (로컬로 또는 Stop 지시문의 결과로).
  • 스트림 간 이동 (다음 / 이전)

참고 : AVS가 보내는 각 URL에 대해 하나 이상의 PlaybackFinished 이벤트가 필요합니다. 여러 URL로 구성된 재생 목록 URL을 수신 한 경우 PlaybackFinished 이벤트를 하나만 보내십시오.


Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackFinished",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": {{LONG}}
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the Play directive.
string
offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long


PlaybackFailed Event

스트림 재생을 시도하는 동안 클라이언트에서 오류가 발생할 때마다 PlaybackFailed 이벤트를 AVS로 전송해야합니다. 
스트림이 재생 중이고 다음 스트림이 버퍼링되지 않는 경우에는 currentPlaybackToken이 payload의 토큰과 다를 수 있습니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackFailed",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "currentPlaybackState": {
                "token": "{{STRING}}",
                "offsetInMilliseconds": {{LONG}},
                "playerActivity": "{{STRING}}"
            },
            "error": {
                "type": "{{STRING}}",
                "message": "{{STRING}}"
            }
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
재생에 실패한 스트림을 나타내는 Play Directive에서 제공하는 opaque token입니다.
string
currentPlaybackState
playbackState 객체의 키 / 값 쌍을 포함합니다.
object
playbackState.token
An opaque token provided by the Play directive.
string
playbackState.offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long
playbackState.playerActivity
Identifies the player state. 
Accepted values: PLAYING, STOPPED, PAUSED, FINISHED, BUFFER_UNDERRUN, or IDLE.
string
error
Contains key/value pairs for error messages.
object
error.type
특정 유형의 오류를 식별합니다. 아래 표는 각 오류 유형에 대한 세부 정보를 제공합니다.
string
error.message
장치가 발생한 오류에 대한 설명. 이것은 기록 목적으로 만 사용됩니다. HTTP 관련 오류의 경우 오류 메시지에 HTTP 오류 응답 본문이 있어야합니다.
string

Error Types

Value
Description
MEDIA_ERROR_UNKNOWN
알 수없는 오류가 발생했습니다.
MEDIA_ERROR_INVALID_REQUEST
서버가 요청이 잘못된 것으로 인식했습니다
E.g. bad request, unauthorized, forbidden, not found, etc.
MEDIA_ERROR_SERVICE_UNAVAILABLE
클라이언트가 서비스에 연결할 수 없습니다.
MEDIA_ERROR_INTERNAL_SERVER_ERROR
서버가 요청을 수락했지만 예상대로 요청을 처리하지 못했습니다.
MEDIA_ERROR_INTERNAL_DEVICE_ERROR
클라이언트에 내부 오류가 있습니다.


Stop Directive

Stop Directive는 클라이언트로 전송되어 오디오 스트림의 재생을 중지합니다. 
귀하의 클라이언트는 음성 요청, 물리적 단추 누르기 또는 GUI 자산의 결과로 Stop 지시문을받을 수 있습니다.

Sample Message

{
    "directive": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "Stop",
            "messageId": "{{STRING}}",
            "dialogRequestId": "{{STRING}}"
        },
        "payload": {
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string
dialogRequestId
A unique ID used to correlate directives sent in response to a specific Recognize event.

Note: dialogRequestId is only sent in response to a speech request. dialogRequestId is not included in directives sent to your client on the downchannel stream.
string


PlaybackStopped Event

클라이언트가 다음 지시문 중 하나를 받고 오디오 스트림 재생을 중지하면 PlaybackStopped 이벤트를 AVS로 보내야합니다.
  • Stop directive
  • REPLACE_ALL의 playBehavior가 포함 된 Play Directive
  • clearBehavior가 CLEAR_ALL 인 ClearQueue Directive

참고 :이 이벤트는 위에 나열된 지시문 중 하나가 수신 된 결과 스트림이 종료 된 경우에만 전송됩니다. 
일반적으로 이것은 사용자 작업의 결과입니다. 스트림 재생이 끝나면이 이벤트를 보내지 않아야합니다 (PlaybackFinished 참조).

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackStopped",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": {{LONG}}
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the Play directive.
string
offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long

PlaybackPaused Event

PlaybackPaused 이벤트는 우선 순위가 높은 입력 / 출력을 수용하기 위해 클라이언트가 콘텐츠 채널에서 오디오를 일시적으로 일시 중지해야 전송됩니다. 우선 순위가 지정된 작업이 완료되면 재생을 다시 시작해야합니다. 
클라이언트는 PlaybackResumed 이벤트를 보내야합니다. 
오디오 입 / 출력의 우선 순위 지정에 대한 자세한 내용은 상호 작용 모델을 참조하십시오.
참고 : 대기 시간을 줄이려면 Recognize 이벤트 후 PlaybackPaused를 보내야합니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackPaused",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided in the Play directive.
string
offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long


PlaybackResumed Event

PlaybackPaused 이벤트 (재생이 우선 순위가 높은 입력 / 출력을 수용하기 위해 콘텐츠 채널에서 일시적으로 일시 중지 된 경우) 후에 재생이 다시 시작되면 PlaybackResumed 이벤트를 AVS로 보내야합니다. 오디오 입 / 출력의 우선 순위 지정에 대한 자세한 내용은 상호 작용 모델을 참조하십시오.

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackResumed",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "offsetInMilliseconds": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string

Payload Parameters

Parameter
Description
Type
token
An opaque token provided in the Play directive.
string
offsetInMilliseconds
Identifies a track's current offset in milliseconds.
long


ClearQueue Directive

ClearQueue 지시문은 AVS에서 클라이언트로 전송되어 재생 대기열을 지 웁니다. 
ClearQueue 지시문에는 다음 두 가지 동작이 있습니다. 
  • CLEAR_ENQUEUED - 대기열을 지우고 현재 재생중인 스트림을 계속 재생합니다. 
  • CLEAR_ALL은 전체 재생 대기열을 지우고 현재 재생중인 스트림을 중지합니다 (해당하는 경우).

Sample Message

{
    "directive": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "ClearQueue",
            "messageId": "{{STRING}}",
            "dialogRequestId": "{{STRING}}"
        },
        "payload": {
            "clearBehavior": "{{STRING}}"
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string
dialogRequestId
A unique ID used to correlate directives sent in response to a specific Recognize event.

Note: dialogRequestId is only sent in response to a speech request. dialogRequestId is not included in directives sent to your client on the downchannel stream.
string
Payload Parameters

Parameter
Description
Type
clearBehavior
대기열 동작을 결정하는 데 사용되는 문자열 값입니다.
Accepted valuesCLEAR_ENQUEUED and CLEAR_ALL
string


PlaybackQueueCleared Event

클라이언트가 ClearQueue directive를 처리 한 후에 PlaybackQueueCleared 이벤트를 AVS로 보내야합니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "PlaybackQueueCleared",
            "messageId": "{{STRING}}"
        },
        "payload": {
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string
Payload Parameters

An empty payload must be sent.


StreamMetadataExtracted Event

클라이언트가 수신하고 재생을 시작하는 오디오 스트림에 메타 데이터를 사용할 수있는 경우 
클라이언트는 원시 데이터로받은 키 / 값 쌍을 가져 와서 해당 쌍을 JSON 객체로 변환해야합니다. 
이 JSON 객체에서 문자열과 숫자는 JSON 문자열로 표현되어야하며 부울은 JSON 불린으로 표현되어야합니다. 
클라이언트는 바이너리 데이터를 포함하는 태그를 걸러 내야합니다. 
예를 들어 클라이언트는 이미지, 이미지 미리보기, 첨부 또는 응용 프로그램 데이터 태그를 AVS로 보내면 안됩니다.

Sample Message

{
    "event": {
        "header": {
            "namespace": "AudioPlayer",
            "name": "StreamMetadataExtracted",
            "messageId": "{{STRING}}"
        },
        "payload": {
            "token": "{{STRING}}",
            "metadata": {
                "{{STRING}}": "{{STRING}}",
                "{{STRING}}": {{BOOLEAN}}
                "{{STRING}}": "{{STRING NUMBER}}"
            }
        }
    }
}

Header Parameters

Parameter
Description
Type
messageId
A unique ID used to represent a specific message.
string
Payload Parameters

Parameter
Description
Type
token
An opaque token provided by the Play directive.
string
metadata
Contains key/value pairs associated with the metadata received.
object


출처 : https://developer.amazon.com/public/solutions/alexa/alexa-voice-service/reference/audioplayer#audioplayer-interface
















저작자 표시 비영리 변경 금지
신고

'Architecture > A.I' 카테고리의 다른 글

PlaybackController Interface  (0) 2017.05.26
Understanding Alerts  (0) 2017.05.26
Alerts Interface  (0) 2017.05.25
AudioPlayer Interface  (0) 2017.05.24

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

Apache Mesos

Architecture 2017.04.18 19:03
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T


Mesos는?

  • 아파치 프로젝트(http://mesos.apache.org/)

  • 트위터, 에어비앤비, 미소스피어가 사용.

  • 기본적으로 Docker 지원.

  • 분산 시스템 커널.

  • 모든 머신에서 동작.

  • 실행 어플리케이션에 대해 리소스 관리와 스케줄링 api를 제공.

  • Mesosphere = Mesos + Marathon + Chrnons

    • Marathon : 작업(컨테이너) 관리 담당.

    • Chronos   : 작업 스케줄러.


  • Mesos 노드 추상화
    • Mesos의 노드들은 모든 Task에 대해 공유 된다.



  • Mesos 동작 구성도
    • Docker는 작업의 Type중 하나이다.
    • Zookeeper를 통해 HA를 구성한다.
    • Scheduler는 Chronos을 사용하거나, 직접 개발이 가능하다.



  • Mesos 구성도 1
    • Marathon은 PaaS플랫폼.
    • 향후 Kubernates(참고) 지원계획.


  • Mesos 구성도2
    • 하이브리드 Cloud 구성가능.
    • Batch 작업은 Chronos로 지원.


  • Mesos Framework
    • Meta-Frameworks / HA Services : Aurora, Marathon
    • Distributed Cron : Chronos
    • Contailners : Docker
    • Continuous Integration : Jenkins, GitLab, GoCD
    • Big Data : Hadoop, Spark, Storm, Kafka, Cassandra, Hypertable, MPI
    • Python workloads : DPark, Exelixi






  • Mesos Architecture





위 그림은 Mesos의 주요 구성 요소를 보여줍니다.

Mesos는 각 클러스터 노드에서 실행되는 에이전트 데몬을 관리하는 마스터 데몬과 이러한 에이전트에서 Task를 실행하는

Mesos 프레임워크로 구성됩니다. 마스터는 리소스 제공을 통해 프레임 워크 전반에서 리소스 (CPU, RAM, ...)를 세밀하게 공유 할 수있게합니다.

각 리소스 오퍼에는 <agent ID, resource1 : amount1, resource2 : amount2, ...> 목록이 포함되어 있습니다

(참고 : 키워드 'slave'는 'agent'를 사용하지 않으므로 드라이버 기반 프레임 워크는 여전히 슬레이브 ID, v1 HTTP API를 사용하는 프레임 워크는 에이전트 ID가있는 오퍼를받습니다.)

마스터는 공정한 공유 또는 엄격한 우선 순위와 같이 주어진 조직 정책에 따라 각 프레임 워크에 제공 할 리소스의 수를 결정합니다.

다양한 정책을 지원하기 위해 마스터는 플러그인 메커니즘을 통해 새로운 할당 모듈을 쉽게 추가 할 수있는 모듈 식 아키텍처를 사용합니다.

Mesos에서 실행되는 프레임 워크는 리소스를 제공 받기 위해 마스터에 등록하는 스케줄러와 프레임 워크의 작업을 실행하기 위해 에이전트 노드에서 실행되는 executor 프로세스로 구성됩니다.

(프레임 워크 스케줄러 및 executors 의 더욱 더 자세한 내용은 App / Framework 개발 가이드 참조 )


마스터가 각 프레임 워크에 제공되는 리소스 수를 결정하는 동안 프레임 워크의 스케줄러는 제공된 리소스 중에서 사용할 리소스를 선택합니다. 프레임 워크가 제공된 자원을 받아들이면 프레임 워크에서 실행하려는 작업에 대한 설명을 Mesos로 전달합니다.

다음 step으로 Mesos는 해당 에이전트에서 Task를 시작합니다.





그림의 이벤트를 살펴 봅시다. 1 . 에이전트 1은 4 개의 CPU와 4GB의 메모리가 있음을 마스터에게보고합니다.

그런 다음 마스터는 할당 정책 모듈을 호출하여 프레임 워크 1에 사용 가능한 모든 리소스가 제공되어야 함을 알립니다.

2. 마스터는 에이전트 1에서 사용할 수있는 것을 프레임 워크 1에 설명하는 리소스 오퍼를 보냅니다. 3. 프레임 워크의 스케줄러는 첫 번째 작업에는 <2 CPU, 1GB RAM>, 두 번째 작업에는 <1 CPU, 2GB RAM>을 사용하여 에이전트에서 실행할 두 가지 작업에 대한 정보로 마스터에 응답합니다. 4. 마지막으로, 마스터는 작업을 에이전트로 보냅니다. 에이전트는 프레임 워크의 executor에게 적절한 자원을 할당하고 두 가지 작업 (그림에서 점선으로 표시)을 시작합니다. CPU 1 개와 RAM 1 개가 아직 할당되지 않았기 때문에 할당 모듈은 프레임 워크 2에 할당 할 수 있습니다. 또한 이 리소스 제공 프로세스는 작업이 완료되고 새 리소스가 해제 될 때 반복됩니다.

Mesos가 제공하는 thin 인터페이스는 확장이 가능하고 프레임 워크가 독립적으로 진화 할 수있게 해주지만 한 가지 질문이 남아 있습니다 : Mesos가 이러한 제약 조건을 안다면 프레임 워크의 제약 조건을 어떻게 만족시킬 수 있습니까?

예를 들어 프레임 워크가 프레임 워크에서 요구하는 데이터를 저장하는 노드를 알면 Mesos없이 어떻게 데이터 지역성을 얻을 수 있습니까?

Mesos는 단순히 프레임 워크에 오퍼를 거부 할 수있는 기능을 부여하여 이러한 질문에 답합니다.

프레임 워크는 제약 조건을 충족시키지 못하는 제안을 거부하고 이를 수용합니다.

특히 프레임 워크가 제한된 시간 동안 입력 데이터를 저장하는 노드를 확보하기 위해 대기하는 지연 스케줄링이라는 간단한 정책이 거의 최적의 데이터 지역을 산출한다는 것을 알게 되었습니다.


출처 : https://www.slideshare.net/songaal/paa-s-mesosmesosphere

        http://mesos.apache.org/

         https://abhishek-tiwari.com/post/building-distributed-systems-with-mesos



저작자 표시 비영리 변경 금지
신고

'Architecture' 카테고리의 다른 글

Apache Mesos  (0) 2017.04.18
아키텍트 지침 15가지!!  (0) 2012.09.14
CBD방법론  (0) 2012.06.04

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

Aho–Corasick string matching algorithm란?

Architecture/algorithm 2016.03.30 17:34
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T



Aho–Corasick string matching algorithm

패턴 집합에 대한 매칭 알고리즘
타 알고리즘 시간 복잡도 : O(m + zn)  - (m : 모든 패턴들의 길이 합, z : 패턴 수, n : text 크기) 

Aho–Corasick 알고리즘 시간 복잡도 : O(m + n + k)  (k : 텍스트 내에 패턴의 발생 수) 

Aho-Corasick 알고리즘을 구현하기 위하여 Keyword Tree, Failure link, Output link 자료구조를 사용하여야 한다.


음..대충 이런 알고리즘이라는 것을 알게 되었다.

좋은 오픈 되어진 소스를 발견!

https://github.com/robert-bor/aho-corasick


디펜던시를 넣고 개발을 하면 되겠다!


메이븐

    <dependency>

        <groupId>org.ahocorasick</groupId>

        <artifactId>ahocorasick</artifactId>

        <version>0.3.0</version>

    </dependency>


그래들

compile('org.ahocorasick:ahocorasick:0.3.0')                            



참고 : https://ko.wikipedia.org/wiki/%EC%95%84%ED%98%B8_%EC%BD%94%EB%9D%BC%EC%8B%9D_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98



  - 끝 -



저작자 표시 비영리 변경 금지
신고

'Architecture > algorithm' 카테고리의 다른 글

Aho–Corasick string matching algorithm란?  (0) 2016.03.30

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

SOLID (object-oriented design)

Architecture/AA 2014.02.26 21:24
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

객체지향적으로 개발 할 때 OOD를 따져서 설계하고 개발한다면 더욱 더 좋은 소스가 될 수 있다.

한번 알아보도록 하자!

 

출처 : http://en.wikipedia.org/wiki/Solid_(object-oriented_design)

 

추억의 솔리드..ㅋㅋㅋㅋㅋ 이밤에 끝을 잡고~

 

Initial Stands for
(acronym)
Concept
S SRP
Single responsibility principle - 단일 책임의 원칙
a class should have only a single responsibility.
하나의 클래스에 오직 하나의 책임이어야 한다는 원칙.
예를 들어 MVC 패턴이 나오기까지...jsp에 모든 것을 다 때려 넣었던 그런
시절이 있었다...단일 페이지에 모든 것을....와우! 그런 것처럼 하나의 클래스에 하나의 책임을 주어서 유지보수와 소스의 가독성, 재사용성을 높일 수 있다.

 ex) Class에 오직 하나의 책임..그렇다면! 메소드도 있는데???

그렇다! 하나의 Class에 여러가지 메소드가 있을 것이다.

그 메소드들이 Class들 마다 하는 역할을 구분하여 오직 하나의 역할(책임)을 줘야 한다는 뜻이다.

 

즉, public class acetData{

          public void load(){

             .........................

           }

 

          public void save(){

             .........................

           }

 

          public void del(){

             .........................

           }

 

           public void displayToUi(AcetVo acetVo){

             .........................

           }       

     }

 

위의 클래스에서 Data와 관련 된 메소드는

데이터를 load

데이터를 save

데이터를 del

이렇게 3가지이며, 데이터 관련 책임이라고 볼 수 있으며,

displayToUi는 UI 화면에 데이터를 뿌려주는 것! 즉, 화면에 보여주는 책임이라고

볼 수 있다.  displayToUi는 UI Class로 빼줘야 한다.

 

 

O OCP
Open/closed principle - 개방 폐쇄의 원칙
“software entities … should be open for extension, but closed for modification.”
요녀석은 확장에 대한 open~!!!!! closed는 수정에 대한 내용이다. 라고 대부분
나와있다..ㅋㅋㅋㅋ 여기에서 중요한 것은!!! 확장이다! 영어로 extension~!!
수정에 대한 closed 즉, 수정이 되면 안된다는 것이다. 어떨때??? 확장 땜시롱!
확장을 위해! open! 확장이 매우 용이하게!! 그렇다고 본 소스를 마구마구 수정하면 No!! 즉, 수정에 대한 것은 closed!! 결론적으로 확장을 잘하기 위한 원칙이다.
바로 상속의 개념인 것이다. 즉, 공통적인 부분을 추상하여 SubClass나 SubType으로 표현한다. 자세히 말하면 바로 SubClass(extends), SubType(implements) 인 것이다.
L LSP
Liskov substitution principle - 리스코프 치환 원칙
“objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.” See also design by contract.

너무나도 헷깔렸던 개념이다..-_-;;
그 이유가 SubClass와 SubType 차이를 몰랐었고...OCP나 LSP는 요 2가지로 표현이 된다는 것이다..
특히 위에 나오는 영어에서도 보면 subType의 인스턴스가 교체된다는 것인데...
여기에서 교체된다는 말이 code로 표현을 어떻게 해줘야하는건지...잘 떠오르지 않았다..주변 동료에게 이런저런 이야기를 같이 해보다가...알게 되었다^-^
우선 정의를 보도록 하자.
정의 : 
1) SuperClass(상위타입)을 SubClass(하위타입)로 교체(치환)해도 정상 작동 해야 한다.       
또는 2) SuperType(상위타입)을 SubType(하위타입)로 교체(치환)해도 정상 작동 해야 한다.      

        1)은 Class기반의 상속을 생각하면 된다.

        2)는 Interface 기반의 상속(구현)을 생각하면 된다.

 

        1)은 말그대로 객체를 치환하여도 같은 동작을 하면 OK!!

        2) 객체를 치환한다는 개념으로 접근하기보다 SubType의 기능 수행으로

            생각하면 된다. ex) dataSave()면 데이터 저장인데 그 안에서 modify기능을

            하면 안된다.

 

         이 원칙은 OCP를 잘 구현하기 위해 체크하는 스펙 같은거라고 보면 될 것 같다.

         반대로 말하면 리스코프 치환 원칙을 지키지 않으면 OCP를 지키지 않을

         가능성이 커진다는 것이다.

 

         특히 2번, 인터페이스 기반에서는 치환이라는 개념 자체가 이해가 가질 않았을

         것이다..그러므로 기능, 리턴, 예외 등 올바른 작동을 하는지 봐야 한다.


참고 사이트
1)http://www.cs.princeton.edu/courses/archive/fall98/cs441/mainus/node12.html
2) http://vandbt.tistory.com/41
3) http://hyukmini.tistory.com/16    

I ISP
Interface segregation principle - 인터페이스 분리 원칙
“many client-specific interfaces are better than one general-purpose interface.”[4]
 
많은 뚜렷한 인터페이스들은 하나의 일반적인 취지의 인터페이스보다 낫다.
옹마~앙대요~~왜이리 말이 어려운지.....OTL =3=3
 
인터페이스 분리 원칙은..클라이언트를 기준으로 인터페이스를 분리하는 원칙.
이 말을 다시 풀어보면..
 
각 클라이언트가 사용하는 기능을 중심으로 인터페이스를 분리함으로써,
클라이언트로부터 발생하는 인터페이스 변경의 여파가 다른 클라이언트에 미치는 영향을 최소화 할 수 있게 된다.

        생각해보자! 기능 중심?????? 인터페이스를 분리해??? Why??

        인터페이스를 하나 만들려고 한다. 그 안에는 여러가지 메소드들이

        많이 있을 것이다.

        즉, ISP의 원칙을 잘모른다면..동작의 역할 인 메소드들이 뒤죽박죽

        하나의 인터페이스에 얽혀있을 것이다.

        하지만 ISP를 잘~~알고 인터페이스를 만든다고 하면! 바로 기능중심!!! 으로

        나눠서 이쁘게 잘~~~쓰게 될 것이다.

 

    참고문헌 : 개발자가 반드시 정복해야 할 객체지향과 디자인 패턴(최범균 저)

 

D DIP
Dependency inversion principle - 의존관계 역전의 법칙
one should “Depend upon Abstractions. Do not depend upon concretions.”[4]
Dependency injection is one method of following this principle.

       DI(Dependency Injection)이라고 보면 된다. springframework의 특징

      중인 IoC/DI 이다. 커플링을 최소화시키며(외부주입을 해주니깐!)

 

      특히, 생성자 또는 setter로 주입을 시키는 특징이 있다.

 

 

 

 

 

 

                 - END -

저작자 표시 비영리 변경 금지
신고

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] Decorator Pattern

Architecture/DesignPattern 2014.01.27 09:28
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

Decorator Pattern


 개요

 클래스 다이어그램

 예제(Java)

 같이보기

 참고 사항


<< 개요 >>

Decorator Pattern 이란?

 

데코레이터 패턴(Decorator pattern)이란 주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴으로, 기능 확장이 필요할 때 서브클래싱 대신 쓸 수 있는 유연한 대안이 될 수 있다.

(출처 : 위키피디아 - http://ko.wikipedia.org/wiki/%EB%8D%B0%EC%BD%94%EB%A0%88%EC%9D%B4%ED%84%B0_%ED%8C%A8%ED%84%B4)

 

의도

객체에 동적으로 새로운 서비스를 추가

기능 추가를 위해 서브클래스를 생성 하는 것 보다 융통성이 있음.

 

 

아래의 로봇 사진 출처 : http://blog.naver.com/PostView.nhn?blogId=romantico_q&logNo=50185115988

 

변신 합체 로봇!! 페가서스 라고 하네요^^;;

데코레이터 패턴을 학습 하면서 기억에 많이 남을만한 예제가 없을까? 라고 생각하던 차에..변신합체 로봇을 통해 학습하면 좋겠다고 생각하게 되었습니다..ㅋㅋㅋㅋ;;

 

우리의 변신합체 로봇들을 소개 합니다.

우리의 메인 로봇인 왼쪽 - 파랭이 로봇!!

그 외 몸통이 될 가운데 로봇, 다리가 되어줄 빨갱이 로봇ㅋㅋ

 

하일라이트로 다시 한번 변신을 시켜줄 우리의 독수리 로봇이 되겠습니다.

 

 

 

1) 머리(우리의 메인)

 

2) 몸통(합체 되어질)

 

3) 다리(합체 되어질)

 

 

쫘잔~~~+ㅁ+/

 

 

 

아래처럼 합체로봇으로 변신하게 됩니다.

 

 

여기서 다가 아닙니다!! 변신합체 로봇에서 다시 한번 독수리가 합체가 되어서

그 유명한!! 페가서스가 되어집니다!!!! 쫘잔~~~~~~+ㅁ+/

 

변신합체 로봇! 페가서스!!!! 두둥~

자! 데코레이터 패른!!! 시작 해볼까용?~~

개요는 마무리 하고, 먼저 패턴의 클래스 다이어그램을 먼저 살펴 보겠습니다.

 

<< 클래스 다이어그램 >> 

그냥 한번 그려보았다..;;

 

아래와 비교해보면 인터페이스와 추상클래스간의 관계를 그리지 않은 것 같다. 참고하자!

 

<< 예제(Java) >>

1) 결과

   아래의 결과와 같이 변신은 메인 로봇이 머리로! 그 다음엔 바디, 그 다음 다리, 그 다음 뒷다리로 변신이

   되어집니다. ㅋㅋㅋ 전투력은 무려 10만이 넘어가네요+ㅁ+/

Change Center Robot -> Body Combine!!
Change Red Robot -> Combine Leg!!!
Change egle Robot -> Back Leg Combine!!
Main Robot Combine!! to Head, Combine Body!!, Combine Leg!!, Combine Back Leg!!
total power is..103100

 

 

    2) 테스트 코드   

package kr.pe.acet.decorator;

import org.junit.Assert;
import org.junit.Test;

public class DecoratorPatternTest {

 @Test
 public void test() {
  
  Robot mRobot = new BacklegCombine(new LegCombine(new BodyCombine(new  MainRobot())));
  
  Assert.assertNotNull(mRobot);
  
  System.out.println(mRobot.getCombineAction());
  System.out.println("total power is.."+mRobot.getPower());
  
 }

}

 

 

    3) Robot Interface(Decorator pattern에서 중요하게 봐야 할 부분 입니다.)

package kr.pe.acet.decorator;

public interface Robot {
 public String getCombineAction();
 public int getPower();
}
 

 

 

 

    4) MainRobot class

package kr.pe.acet.decorator;

public class MainRobot implements Robot{

 @Override
 public String getCombineAction() {
  // TODO Auto-generated method stub
  return "Main Robot Combine!! to Head";
 }

 @Override
 public int getPower() {
  // TODO Auto-generated method stub
  return 100;
 }
}
 

 

 

    5) CombineDecorator class (Decorator pattern에서 중요하게 봐야 할 부분 입니다.)

package kr.pe.acet.decorator;

public abstract class CombineDecorator implements Robot{
 protected Robot tempRobot;
 
 public CombineDecorator(Robot newRobot){
  tempRobot = newRobot;
 }
 
 public String getCombineAction() {
  // TODO Auto-generated method stub
  return tempRobot.getCombineAction();
 }

 public int getPower() {
  // TODO Auto-generated method stub
  return tempRobot.getPower();
 }
  
}
 

 

 

    6) BodyCombine class

package kr.pe.acet.decorator;

public class BodyCombine extends CombineDecorator{

 public BodyCombine(Robot newRobot) {
  super(newRobot);
  System.out.println("Change Center Robot -> Body Combine!!");
 }

 public String getCombineAction() {
  // TODO Auto-generated method stub
  return tempRobot.getCombineAction()+", Combine Body!!";
 }

 public int getPower() {
  // TODO Auto-generated method stub
  return tempRobot.getPower()+2000;
 }

}
 

 

 

    7) LegCombine class

package kr.pe.acet.decorator;

public class LegCombine extends CombineDecorator{

 public LegCombine(Robot newRobot) {
  super(newRobot);
  System.out.println("Change Red Robot -> Combine Leg!!!");
 }
 
 public String getCombineAction() {
  // TODO Auto-generated method stub
  return tempRobot.getCombineAction()+", Combine Leg!!";
 }

 public int getPower() {
  // TODO Auto-generated method stub
  return tempRobot.getPower()+1000;
 }

}
 

 

 

 8) BacklegCombine class

package kr.pe.acet.decorator;

public class BacklegCombine extends CombineDecorator{

 public BacklegCombine(Robot newRobot) {
  super(newRobot);
  System.out.println("Change egle Robot -> Back Leg Combine!!");
 }

 public String getCombineAction() {
  // TODO Auto-generated method stub
  return tempRobot.getCombineAction()+", Combine Back Leg!!";
 }

 public int getPower() {
  // TODO Auto-generated method stub
  return tempRobot.getPower()+100000;
 }

}
 

 

 

 

<< 같이 보기 >>

http://www.youtube.com/watch?v=j40kRwSm4VE

정말 도움이 많이 된 동영상 입니다. 참고하세요~꼭 보세요~!!

내 책에 있던 소스 코드

 

또 다른 소스 참고! : https://github.com/colorbox/Gof/tree/master/java/Decorator

 

<< 참고 사항 >>

데코레이터 패턴은 객체에 동적으로 새로운 무엇인가를 하고자 할 때 사용 된다. 특히 상속으로 sub Class를 이용하는 것 보다 더 유연성 있게 추가 할 수 있다.

 

 

 

저작자 표시 비영리 변경 금지
신고

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

  • Favicon of http://7network.tistory.com BlogIcon 개굴개굴왕 2014.08.05 14:09 신고 답글 | 수정/삭제 | ADDR

    안녕하세요. 블로그 내용이 좋아서♡ 블로그모음 서비스인 블로그앤미[http://blogand.me] 에 등록했습니다. 원하지 않으시면 삭제하겠습니다. 좋은 하루 되세요. ^^

    • Favicon of http://acet.pe.kr BlogIcon String Ace-T 2014.08.05 17:08 신고 수정/삭제

      ㅎㅎㅎ블로그모음 서비스도 있었군요! 등록해주셔서 감사합니다^^
      그리고 번창하시길 바랍니다~

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] Chain of responsibility pattern

Architecture/DesignPattern 2014.01.20 09:24
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

Chain of responsibility Pattern


 개요

 예제(Java)

 같이보기

 참고 사항


<< 개요 >>

Chain of responsibility Pattern 이란?

                                                           (참고 사이트 : 위키피디아 - http://ko.wikipedia.org/wiki/Chain_of_responsibility_%ED%8C%A8%ED%84%B4)

객체 지향 디자인에서 chain-of-responsibility pattern은 명령 오브젝트와 일련의 프로세스 오브젝트를 포함하는 디자인 패턴이다. 각각의 프로세스 오브젝트는 명령 오브젝트를 핸들할 수 있는 연산의 집합으로 이루어지고, 체인안의 프로세스 오브젝트가 핸들할 수 없는 행해진다. 이 작동방식은 새로운 프로세스 오브젝트에서 체인의 끝까지에도 포함된다.

표준 chain-of-responsibility model이 변화하면서, 몇몇 핸들러들은 다양한 방향으로 명령을 보내 책임을 트리 형태로 바꾸는 관제사 역할을 하기도 한다. 몇몇 경우에서는, 프로세스 오브젝트가 상위의 프로세스 오브젝트와 명령을 호출하여 작은 파트의 문제를 해결하기 위해 재귀적으로 실행된다. 이 경우 재귀는 명령이 처리되거나 모든 트리가 탐색될때까지 진행되게 된다. XML(파싱되었으나 실행되지 않은)인터프리터가 알맞은 예가 된다.

이 패턴은 결합을 느슨하게 하기 위해 고안되었으며 가장 좋은 프로그래밍 사례로 꼽힌다.

라고는 되어있는데 무슨 내용인지...처음에는 전혀 Feel을 느낄 수 가 없었다..:D


우선은 아래의 예제를 보고 어떤 녀석인지 감을 잡아보도록 하자.

아! 예제를 보기전에 클래스 다이어그램을 보도록 하자.


<< 예제(Java) >>

예제는 사칙연산에 대해서 구현을 해보겠다. 참고사항의 동영상에 나오는 소스이다.

이해 돕기에 좋은 소스 인 것 같아서 선택하였다! ㅋㅋ


위의 클래스 다이어그램 처럼 우선 Interface인 Handler를 구현하여 보자. 명명은 Chain으로 하겠다.

1) Chain Interface : 2가지로 구성 되어질 수 있는데 하나는  객체를 엮을 수 있는(Chain) 

    setNextChain()이고, 또 다른 하나는 구현하여 사용하게 되는 calculate() 이다.

package kr.pe.acet.chainOfResposibility;

public interface Chain {

public void setNextChain(Chain nextChain);

public void calculate(Numbers req);

}


2) Chain의 구현부에서 사용 되어 질 Numbers.java를 만들어보자.

    내부 구조는 계산 되어질 숫자형 2개, 어떤 작업인지를 뜻하는 String 으로 변수가 구성되어져있다.

    그리고 생성자와 getter 들이 있다.

package kr.pe.acet.chainOfResposibility;

public class Numbers {


private int number1;

private int number2;

private String calculationWanted;

public Numbers(int number1, int number2, String calWanted){

this.number1 = number1;

this.number2 = number2;

this.calculationWanted = calWanted;

}


public int getNumber1() {

return number1;

}


public int getNumber2() {

return number2;

}


public String getCalculationWanted() {

return calculationWanted;

}

}



3) Chain Interface의 구현부들(

   - AddNumbers.java

package kr.pe.acet.chainOfResposibility;

public class AddNumbers implements Chain{

private Chain nextInChain;


@Override

public void setNextChain(Chain nextChain) {

this.nextInChain = nextChain;

}


@Override

public void calculate(Numbers req) {


if(req.getCalculationWanted() == "add"){

System.out.println(req.getNumber1()+" + "+req.getNumber2()+"="+(req.getNumber1()+req.getNumber2()));

}else{

            nextInChain.calculate(req);

}

}


}



   - SubtractNumbers.java

package kr.pe.acet.chainOfResposibility;

public class SubtractNumbers implements Chain{

private Chain nextInChain;


@Override

public void setNextChain(Chain nextChain) {

this.nextInChain = nextChain;

}


@Override

public void calculate(Numbers req) {


if(req.getCalculationWanted() == "sub"){

System.out.println(req.getNumber1()+" - "+req.getNumber2()+"="+(req.getNumber1()-req.getNumber2()));

}else{

            nextInChain.calculate(req);

}

}


}



   - MultiNumbers.java

package kr.pe.acet.chainOfResposibility;

public class MultiNumbers implements Chain{

private Chain nextInChain;


@Override

public void setNextChain(Chain nextChain) {

this.nextInChain = nextChain;

}


@Override

public void calculate(Numbers req) {


if(req.getCalculationWanted() == "multi"){

System.out.println(req.getNumber1()+" * "+req.getNumber2()+"="+(req.getNumber1()*req.getNumber2()));

}else{

            nextInChain.calculate(req);

}

}


}



   - DivideNumbers.java

package kr.pe.acet.chainOfResposibility;

public class DivideNumbers implements Chain{

private Chain nextInChain;


@Override

public void setNextChain(Chain nextChain) {

this.nextInChain = nextChain;

}


@Override

public void calculate(Numbers req) {


if(req.getCalculationWanted() == "div"){

System.out.println(req.getNumber1()+" / "+req.getNumber2()+"="+(req.getNumber1()/req.getNumber2()));

}else{

            System.out.println("Only works for add, sub, mult, div~!!");

}

}


}



4) Test Code

package kr.pe.acet.chainOfResposibility;

import static org.junit.Assert.*;


import org.junit.Test;


public class ChainOfResponsibilityTestCode {


@Test

public void chainOfResponsibilityTest() {

Chain chainCal1 = new AddNumbers();

Chain chainCal2 = new SubtractNumbers();

Chain chainCal3 = new MultiNumbers();

Chain chainCal4 = new DivideNumbers();

chainCal1.setNextChain(chainCal2);

chainCal2.setNextChain(chainCal3);

chainCal3.setNextChain(chainCal4);

              //Numbers request = new Numbers(10, 29, "add");

             //Numbers request = new Numbers(10, 29, "multi");

Numbers request = new Numbers(10, 29, "acet");

chainCal1.calculate(request);

}


}



5) 결과

Numbers request = new Numbers(10, 29, "add");   일 경우

     : 10 + 29=39     

   

Numbers request = new Numbers(10, 29, "multi"); 일 경우

10 * 29=290


Numbers request = new Numbers(10, 29, "acet"); 일 경우는???

이 답을 대답 할 수 있다면 Chain of responsibility pattern을 이해가 된 것이라고 생각이 든다!

[ Only works for add, sub, mult, div~!! ] => 답은 드래그~~~:D



<< 같이 보기 >>

인터프리터 패턴과 비슷한 느낌을 받았다.


study : 


굿택님 - 패턴정의 소개, 클래스 다이어그램 소개, 클라이언트에서 핸들러에게 책임을 주면 줄을 서있고 차레차레 일을 전달

Handler : Request를 처리 하기 위한 인터페이스를 정의, 다음 것의 링크를 정의

이 패턴의 목적은 객체간의 의존성을 약화시킨다.

예제 시연..


라낑님 : 위키피디아 개념 설명, 로그 관련 예제 시연, 스프링 시큐리티- 서블릿필터 예제 


<< 참고 사항 >>

동영상 사이트 :  http://www.youtube.com/watch?v=jDX6x8qmjbA


동영상에 외국인 아저씨가 코딩 한대로 했는데...틀린 부분이 있었다!!!!

if(req.getCalculationWanted() == "add"){

if(req.getCalculationWanted() == "div"){

요런 녀석들은...equals를 사용하는게 맞다^-^;

if(req.getCalculationWanted().equals("add")){

if(req.getCalculationWanted().equals("div")){



               - END -





저작자 표시 비영리 변경 금지
신고

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] Visitor pattern

Architecture/DesignPattern 2014.01.11 17:53
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

Visitor Pattern


 개요

 예제(Java)

 같이보기

 참고 사항


<< 개요 >>

Visitor Pattern -  구조안을 돌아다니면서 일을 한다.


네이버 어학사전

(software, design, ) A behavioural design pattern that separats an algorithm from an object structure on which it operates. 


- 행위 디자인 패턴이고 객체 구조로부터 분리하는 하나의 방법이다. 이런 분리는 존재하고 있는 객체 구조에 그 구조를 수정하지 않고 새로운 동작을 추가 할 수 있도록 해준다. 이것은 open-closed principle에 따르는 하나의 방법이다.


또한, 오퍼레이션!! 동작이라고 생각하자.

비지터 패턴은 객체의 요소에 대해 수행하는 오퍼레이션을 나타낸다.

즉,  visitor(방문자)는 자신의 오퍼레이션의 대상이 되는 요소를 갖는 클래스를 수정하지 않고 새로운 오퍼레이션을 정의하는게 가능케한다.

적용영역으로 객체의 구조를 정의하는 클래스가 잘 변하지는 않으나, 구조 상에서 새로운 오펄이션을 정의 하고자 하는 경우나 하나의 객체에 대해서 관련이 적은, 상이한 오퍼레이션을 수행 할 필요가 있는 경우, 이러한 오퍼레이션에 의해 클래스가 난잡하게 되는 것을 막기 위해 사용한다.


요약하자면

1) 새로운 오퍼레이션 추가가 용이.

2) Visitor는 관련 있는 오퍼레이션을 묶고, 관련이 적은 오퍼레이션을 분리 시킨다.(OCP)

3) Visitor의 사용은 ConcreteElement Interface가 내부상태에 접근 할 수 있는 공개된 오퍼레이션 제공을 요구하며, 캡슐화(encapsulation)를 약화 시킨다.(단점?)


위의 말들이 맞는지는 아래를 보면서 확인 해보자.(사실 위의 말들이...처음에는 뭔소린가? 할 것이다ㅋㅋ)


[클래스 다이어그램]


<< 예제 Java >>

어떤 예제가 좋을까...고민하다가 비지터니깐 베지터로 해야겠다는 생각을 했다 ㅋㅋ

즉, Visitor == 베지터(Vesiter)가 된다. 캬캬; 

자! 그럼 재미있는 코딩을 해보자 ㅋㅋ      


결과부터 보면..

[ 결과 ]

베지터가 손오공과 함께 나메크성에 방문 하였습니다.

베지터가 프리저에게 대항하여 지구에서 전투 중입니다. 


[테스트 코드]

package kr.pe.acet.visitor;

import static org.junit.Assert.*;


import org.junit.Test;


public class VisitorTestCode {


@Test

public void visitorTest() {

Namek namekSung = new Namek("손오공");

namekSung.accept(new VisitPlanet());


Earth earth = new Earth("프리저");

earth.accept(new VisitPlanet());

}


}

 


자 이제 클래스 다이어그램을 보고 소스를 짜보자! 

우선 2개의 interface가 필요하다는 것을 알 수 가 있다.

Element, Visitor

1) Visitor(베지터) - 방문자

package kr.pe.acet.visitor;

public interface Vesiter {

public void visit(Namek namek);   // 나메크행성 방문

public void visit(Earth earth);        // 지구 방문

}



2) Element는 Accepter(수용자)의 역할을 한다.    즉, Vesiter의 동작이 방문할 곳을 나타내는 동작을 한다. 방문자(베지터)를 받아들이는 accept 메소드를 선언한다. accept 메소드의 인수로는 베지터의 오퍼레이션(동작)을 넘겨진다.


Accepter(수용자)

package kr.pe.acet.visitor;

public interface Accepter {

public void accept(Vesiter v);


}


3) 베지터 구현 소스 - VisitPlanet 

package kr.pe.acet.visitor;

public class VisitPlanet implements Vesiter{


@Override

public void visit(Namek namek) {

// TODO Auto-generated method stub

System.out.println("베지터가 "+namek.getName()+"과 함께 나메크성에 방문 하였습니다.");

}


@Override

public void visit(Earth earth) {

// TODO Auto-generated method stub

System.out.println("베지터가 "+earth.getName()+"에게 대항하여 지구에서 전투 중입니다.");

}


}



4) 수용자(Accepter) 구현 소스 - Namek 

package kr.pe.acet.visitor;

public class Namek implements Accepter{

String name;

public Namek(String name){

this.name= name;

}

public String getName() {

return name;

}


@Override

public void accept(Vesiter v) {

v.visit(this);

}


}

 


5) 수용자(Accepter) 구현 소스 - Earth 

package kr.pe.acet.visitor;

public class Earth implements Accepter{


private String name;

public Earth(String name) {

this.name=name;

}


public String getName() {

return name;

}


@Override

public void accept(Vesiter v) {

v.visit(this);

}


}

 


위에서 구조를 하나 더 넣어보면..!!


<< 같이 보기 >>

스터디 - 2014.01.13

  라낑님 : 구조에서 분리 시키는 방법. 행위에 관련 된 것을 인터페이스로 뽑아 냄. 

              위키피디아 소스로 진행.

              구조에 대한 정의는 미리 Visitor 인터페이스로 정의(Wheel, Engine, Body 등등)

  굿택님 : 객체구조를 비지터가 방문하여 뭔가를 빼낸다고 이해 함.

              내가 짠 소스를 비유하면 나메크성과 지구가 객체구조이고, 베지터가 방문을 한다고 보면 된다.

             Acceptor가 받아줘야 함. 받아줬을 때만 방문을 허락 함. ppt 파일 소개, 예제 확인(야동관련).


<< 참고 사항 >>

다시 보도록 하자. 사실 위에서 말했던 "구조를 수정하지 않고 새로운 동작을 추가 할 수 있도록 해준다"에서 구조라는 것이 헷깔렸었다..스터디를 통해서 정확히 알 수 있었다.

여기에서 구조라는 것은 Visitor의 구조 이다. 즉, 베지터의 구조 이다.

베지터의 구조!!

        public void visit(Namek namek);   // 나메크행성 방문

public void visit(Earth earth);


이 구조를 가지고 새로운 동작을 추가!! 즉, VisitPlanet 와 같은 동작을 쉽게! 추가 할 수 가 있다. 

AttackPlanet을 하나 추가 해보자!


- Attackplanet.java

package kr.pe.acet.visitor;

public class AttackPlanet implements Vesiter{


@Override

public void visit(Namek namek) {

// TODO Auto-generated method stub

System.out.println("베지터가 "+namek.getName()+"과 함께 나메크성에 공격 하였습니다.");

}


@Override

public void visit(Earth earth) {

// TODO Auto-generated method stub

System.out.println("베지터가 "+earth.getName()+"에게 대항하여 지구에서 전투 중입니다.");

}


}

 




행위 디자인 패턴이고 객체 구조로부터 분리하는 하나의 방법이다. 이런 분리는 존재하고 있는 객체 구조에 그 구조를 수정하지 않고 새로운 동작을 추가 할 수 있도록 해준다. 이것은 open-closed principle에 따르는 하나의 방법이다.


필자는..구조가 너무 헷깔려서...Moon이라는 Class를 추가하여 새로운 동작을 추가 하고자 했었다..


자신의 오퍼레이션의 대상이 되는 요소를 갖는 클래스를 수정하지 않고 새로운 오퍼레이션을 정의하는게 가능케한다."

에서도 마찬가지이다. 클래스를 수정하지 않는다에서의 클래스는 Visitor 이며, 새로운 오퍼레이션이라는 것은 VisitPlanet같은 Visitor의 구현체인 것이다.



- END -

    

저작자 표시 비영리 변경 금지
신고

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] Iterator pattern

Architecture/DesignPattern 2014.01.06 17:41
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T


Iterator Pattern


 개요

 예제(Java)

 같이보기

 참고 사항


<< 개요 >>

Iterator Pattern -  하나씩 열거하면서 처리 한다.

 

 


<< 예제(Java) >>

1. 결과 

실용주의 프로그래머
애자일 프로젝트
파워 스피치
왜 일하는가?


2. 테스트 코드 

 package kr.pe.acet.iterator;

 

public class AggregateTest {
    @org.junit.Test
    public void testIterator() throws Exception {
        BookShelf bookShelf = new BookShelf(4);

        bookShelf.appendBook(new Book("실용주의 프로그래머"));
        bookShelf.appendBook(new Book("애자일 프로젝트"));
        bookShelf.appendBook(new Book("파워 스피치"));
        bookShelf.appendBook(new Book("왜 일하는가?"));

        Iterator it = bookShelf.iterator();

        while(it.hasNext()){
            Book book = (Book)it.next();

            System.out.println(book.getName());
        }
    }

}

 

3.Aggregate  

      package kr.pe.acet.iterator;

import java.util.Iterator;

public interface Aggregate {
    public abstract kr.pe.acet.iterator.Iterator iterator();
}

4. BookShelf 

 package kr.pe.acet.iterator;


public class BookShelf implements Aggregate {

    private Book[] books;

    private int last = 0;

    public BookShelf(int maxsize){
        this.books = new Book[maxsize];
    }

    public Book getBookAt(int index){
        return books[index];
    }

    public void appendBook(Book book){
        this.books[last] =  book;
        last++;
    }
    public int getLength(){
        return last;
    }
    @Override
    public Iterator iterator() {
        // TODO Auto-generated method stub
        return new BookShelfIterator(this);
    }
}

 

5. BookShelfIterator 

 package kr.pe.acet.iterator;

public class BookShelfIterator implements Iterator{
    private BookShelf bookShelf;

    private int index;

    public BookShelfIterator(BookShelf bookShelf){
        this.bookShelf = bookShelf;
        this.index = 0;
    }

    public boolean hasNext(){
        if(index < bookShelf.getLength()){
            return true;
        }else{
            return false;
        }
    }
    public Object next(){

        Book book = bookShelf.getBookAt(index);
        index++;
        return book;
    }
}

 

6. Iterator 

package kr.pe.acet.iterator;

public interface Iterator {
    public abstract boolean hasNext();
    public abstract Object next();
}

 

 

<< 같이 보기 >>

1. Visitor pattern

2. Composite pattern

3. Factory Method pattern


<< 참고 사항 >>

1.Java 언어로 배우는 디자인 패턴 입문



저작자 표시 비영리 변경 금지
신고

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] flyweight pattern

Architecture/DesignPattern 2014.01.06 17:37
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T


Flyweight Pattern


 

 개요

 클래스 다이어그램

 예제(Java)

 같이보기

 참고 사항

 

 

 

<< 개요 >>

Flyweight - 동일한 것을 공유해서 낭비를 없앤다.

이 디자인패턴은 객체를 '가볍게' 하기 위함 이다. 여기에서의 가볍다라는 것은 메모리의 사용량을 말한다.

한마디로 인스턴스를 가능한 공유시켜서 쓸데없이 new를 하지 않는 것이다.

 

 

<< 클래스 다이어그램 >> 


<< 예제(Java) >>

 

결과

 객체 생성!?
aceHunter님이1레벨이 되어 arrowShotting skill을 사용 할 수 있습니다.
aceHunter님이1레벨이 되어 doubleArrowShotting skill을 사용 할 수 있습니다.
aceHunter님이30레벨이 되어 arrowShotting 10발 skill을 사용 할 수 있습니다.
객체 생성!?
highHunter님이120레벨이 되어 arrowShotting 10발 skill을 사용 할 수 있습니다.
highHunter님이120레벨이 되어 슈퍼!! doubleArrowShotting skill을 사용 할 수 있습니다.

 

 

테스트 코드 

package kr.pe.acet.flyweight;

import static org.junit.Assert.*;
import kr.pe.acet.flyweight.HunterKind;
import kr.pe.acet.flyweight.HunderVilage;

import org.junit.Test;

public class FlyweightTest {

 @Test
 public void flyweightHunterLevleUpTest() {
  HunderVilage hunter = null;
  HunterKind acet = null;
  
  hunter= HunderVilage.getInstance();
  
  acet = hunter.getFlyweightHunter("aceHunter",1);
  acet.arrowShotting();
  acet.doubleArrowShotting();
  
  acet = hunter.getFlyweightHunter("aceHunter",30);
  acet.arrowShotting();
  acet.doubleArrowShotting();
  
  acet = hunter.getFlyweightHunter("highHunter",120);
  acet.arrowShotting();
  acet.doubleArrowShotting();
 }

}

 

Flyweight 소스 - interface

 package kr.pe.acet.flyweight;

public interface Hunter {
 
 // Lv 1
 public void arrowShotting();
 
 // lv 2
 public void doubleArrowShotting();
}

 

Flyweight 구현부 

package kr.pe.acet.flyweight;

public class HunterKind implements Hunter{

 private int lv;
 private String shareObj;

 public HunterKind(String shareObj) {
  this.shareObj = shareObj;
 }
 
 public void setLv(int lv) {
  this.lv = lv;
 }

 @Override
 public void arrowShotting() {
  // TODO Auto-generated method stub
  if(lv == 1){
   System.out.println(shareObj+"님이"+lv+"레벨이 되어 arrowShotting skill을 사용 할 수 있습니다.");
  }else if(lv > 20){
   System.out.println(shareObj+"님이"+lv+"레벨이 되어 arrowShotting 10발 skill을 사용 할 수 있습니다.");
  }
 }

 @Override
 public void doubleArrowShotting() {
  // TODO Auto-generated method stub
  if(lv == 1){
   System.out.println(shareObj+"님이"+lv+"레벨이 되어 doubleArrowShotting skill을 사용 할 수 있습니다.");
  }else if(lv > 100){
   System.out.println(shareObj+"님이"+lv+"레벨이 되어 슈퍼!! doubleArrowShotting skill을 사용 할 수 있습니다.");
  }
  
 }

}

 

 

 

Flyweight Factory 소스 

package kr.pe.acet.flyweight;

import java.util.HashMap;

public class HunderVilage {

 public HashMap<String, HunterKind> hunterSchool = new HashMap<String, HunterKind>();
 
 public HunderVilage(){
  
 }
 
 
 private static HunderVilage singletonHunter;
 public static HunderVilage getInstance(){
        if(singletonHunter == null){
            synchronized(HunderVilage.class){
                if(singletonHunter == null)
                 singletonHunter = new HunderVilage();
            }
            
        }
        return singletonHunter;
    }
 
 //핵심 코드.
 public synchronized HunterKind getFlyweightHunter(String shareObj, int level)
 {
  HunterKind th = (HunterKind) hunterSchool.get(shareObj);
  if (th == null)
  {
   System.out.println("객체 생성!?");
   th = new HunterKind(shareObj);
   th.setLv(level);
   hunterSchool.put(shareObj, th);
  }else{
   th.setLv(level);
  }
  return th;
 }


}

 

 

hunterSchool에 인스턴스를 종류별로 만들고, 같은 값을 사용하는 인스턴스를 Key 값으로 분류해 사용하면, 매번 new 하지 않아도 되고(new 를 할때 시간소요), 그만큼 메모리도 덜 소비 해서 퍼포먼스를 높일수 있다.

 

추가적으로

Intrinsic 상태 : Flyweight 객체의 내부에 저장 관리 되는 정보

Extrinsic 상태 : Flyweight 객체의 외부에 저장 관리 되는 정보

 


 

<< 같이 보기 >>

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] singleton 패턴


<< 참고 사항 >>

1. http://kimsunzun.tistory.com/entry/Flyweight-%ED%8C%A8%ED%84%B4-1

2. http://jmnote.com/wiki/Flyweight_%ED%8C%A8%ED%84%B4

3. http://www.luciole.kr/133





저작자 표시 비영리 변경 금지
신고

'Architecture > DesignPattern' 카테고리의 다른 글

[DesignPattern] Visitor pattern  (0) 2014.01.11
[DesignPattern] Iterator pattern  (0) 2014.01.06
[DesignPattern] flyweight pattern  (0) 2014.01.06
[DesignPattern] state pattern  (0) 2013.12.31
[DesignPattern] memento pattern  (0) 2013.12.16
[DesignPattern] mediator pattern  (0) 2013.12.09

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] state pattern

Architecture/DesignPattern 2013.12.31 11:26
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T


2013/12/16 - [Architecture/DesignPattern] - [DesignPattern] memento pattern


2013/12/09 - [Architecture/DesignPattern] - [DesignPattern] mediator pattern


2013/12/03 - [Architecture/DesignPattern] - [DesignPattern] command pattern


2013/11/24 - [Architecture/DesignPattern] - [DesignPattern] observer pattern


2013/11/24 - [Architecture/DesignPattern] - [DesignPattern] Interpreter pattern


2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] abstractFactory 패턴


2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] singleton 패턴


 

참고 사이트 : http://www.youtube.com/watch?v=MGEx35FjBuo


<< State Design Pattern은 무엇인가?? >>

1) 내부의 상태가 변경되면 객체의 변경을 허용한다. 객체변경이란 무엇인지는 뒤에~

2) 구조

   - Context            : Concrete State의 구현 클래스의 현재 상태의 인스턴스를 유지한다.                              

   - State               : Context의 행동과 연관된 독특한 상태를  interface로  정의한다.

                              한마디로...상태를 나타내는 역할이다.

   - Concrete State : State의 구현부 이다. 즉, 개개의 상태를 표현하는 역할이다.

3) 참고 그림

   

- 참고사이트 : http://en.wikipedia.org/wiki/State_pattern

[클래스 다이어그램] 



소스  : 테스트 소스


package kr.pe.acet.state;

import org.junit.Assert;

import org.junit.Test;


public class StateTest {


@Test

public void test() {

final StateContext sc = new StateContext();

Assert.assertNotNull(sc);


sc.writeName("Monday");

sc.writeName("Tuesday");

sc.writeName("Wednesday");

sc.writeName("Thursday");

sc.writeName("Friday");

sc.writeName("Saturday");

sc.writeName("Sunday");

}


}


소스 : Context  - Concrete State의 구현 클래스의 현재 상태의 인스턴스를 유지한다.


package kr.pe.acet.state;

public class StateContext {

private Statelike myState;


/**

* Standard constructor

*/

StateContext() {

setState(new StateA());

}


/**

* Setter method for the state. Normally only called by classes implementing

* the State interface.

* @param newState

*            the new state of this context

*/

void setState(final Statelike newState) {

myState = newState;

}


/**

* Writer method

* @param name

*            the name to be written

*/

public void writeName(final String name) {

myState.writeName(this, name);

}

}



소스 : State - Context의 행동과 연관된 독특한 상태를  interface로  정의한다.

package kr.pe.acet.state;

public interface Statelike {

 /**

     * Writer method for the state name.

     * @param context the stateful context

     * @param name the name to be written

     */

    void writeName(StateContext context, String name);

 

}



소스 : Concrete State - State의 구현부 이다.


package kr.pe.acet.state;

public class StateA implements Statelike {


@Override

public void writeName(StateContext context, String name) {

       System.out.println(name.toLowerCase());

       context.setState(new StateB());

}


}




package kr.pe.acet.state;

public class StateB implements Statelike {


/** State counter */

private int count = 0;


@Override

public void writeName(final StateContext context, final String name) {

System.out.println(name.toUpperCase());

/* Change state after StateB's writeName() gets invoked twice */

if (++count > 1) {

context.setState(new StateA());

}

}



}



결과

monday

TUESDAY

WEDNESDAY

thursday

FRIDAY

SATURDAY

sunday




음...뭔가 단순하다. 위의 소스에서 그냥 이것저것 해보자.

결과는 이렇게~

[null]에서[kr.pe.acet.state.StateA@1e63e3d]로 변경 되었습니다.

monday

StateA Excute!!

[kr.pe.acet.state.StateA@1e63e3d]에서[kr.pe.acet.state.StateB@1b90b39]로 변경 되었습니다.

오늘은 월요일 입니다.



TUESDAY

StateB Excute!!

오늘은 화요일 입니다.



WEDNESDAY

StateB Excute!!

[kr.pe.acet.state.StateB@1b90b39]에서[kr.pe.acet.state.StateA@18fe7c3]로 변경 되었습니다.

수요일



[kr.pe.acet.state.StateA@18fe7c3]에서[kr.pe.acet.state.StateB@b8df17]로 변경 되었습니다.

THURSDAY

StateB Excute!!

오늘은 목요일 입니다.



FRIDAY

StateB Excute!!

[kr.pe.acet.state.StateB@b8df17]에서[kr.pe.acet.state.StateA@13e8d89]로 변경 되었습니다.

금요일



[kr.pe.acet.state.StateA@13e8d89]에서[kr.pe.acet.state.StateB@1be2d65]로 변경 되었습니다.

SATURDAY

StateB Excute!!

오늘은 토요일 입니다.



SUNDAY

StateB Excute!!

[kr.pe.acet.state.StateB@1be2d65]에서[kr.pe.acet.state.StateA@9664a1]로 변경 되었습니다.

일요일



[kr.pe.acet.state.StateA@9664a1]에서[kr.pe.acet.state.StateB@1a8c4e7]로 변경 되었습니다.

 


TEST Code

package kr.pe.acet.state;

import org.junit.Assert;

import org.junit.Test;


public class StateTest {


@Test

public void statePatternTest() {

final StateContext sc = new StateContext();

Assert.assertNotNull(sc);


sc.writeName("Monday");

sc.getDay("월요일");

sc.writeName("Tuesday");

sc.getDay("화요일");

sc.writeName("Wednesday");

sc.getDay("수요일");

sc.writeName("Thursday");

sc.getDay("목요일");

sc.writeName("Friday");

sc.getDay("금요일");

sc.writeName("Saturday");

sc.getDay("토요일");

sc.writeName("Sunday");

sc.getDay("일요일");

}


}


Context Code

package kr.pe.acet.state;


// 상태를 관리하거나 

public class StateContext {

private State myState;


/**

* Standard constructor

*/

StateContext() {

setState(new StateA());

}


/**

* Setter method for the state. Normally only called by classes implementing

* the State interface.

* @param newState

*            the new state of this context

*/

void setState(final State newState) {

changeState(newState);

myState = newState;

}


/**

* Writer method

* @param name

*            the name to be written

*/

public void writeName(final String name) {

myState.writeName(this, name);

}

// 상태를 하나 추가 

public void getDay(final String name){

myState.changeName(this, name);

}

// 상태 변화 관리

public void changeState(State state){

System.out.println("["+this.myState+"]에서["+state+"]로 변경 되었습니다.");

}

}


State Code

package kr.pe.acet.state;



// 상태를 나타 냄 

public interface State {

 /**

     * Writer method for the state name.

     * @param context the stateful context

     * @param name the name to be written

     */

    void writeName(StateContext context, String name);    

    void changeName(StateContext context, String name); 

 

}


Concrete State Code - StateA 

package kr.pe.acet.state;


public class StateA implements State {


@Override

public void writeName(StateContext context, String name) {

System.out.println(name.toLowerCase());

System.out.println("StateA Excute!!");

context.setState(new StateB());

}


@Override

public void changeName(StateContext context, String name) {

// TODO Auto-generated method stub

System.out.println(name+"\n\n");

context.setState(new StateB());


}


}


Concrete State Code - StateB

package kr.pe.acet.state;


public class StateB implements State {


/** State counter */

private int count = 0;


@Override

public void writeName(final StateContext context, final String name) {

System.out.println(name.toUpperCase());

System.out.println("StateB Excute!!");

/* Change state after StateB's writeName() gets invoked twice */

if (++count > 1) {

context.setState(new StateA());

}

}


@Override

public void changeName(StateContext context, String name) {

System.out.println("오늘은 "+name+" 입니다.\n\n");

}




}


마지막으로 State Pattern의 장단점은??


장점 : 언제 다른 상태로 변하는지 알 수 있는 정보가 하나의 클래스 내에 정리되어 있는 점이다.

즉, 위의 Concrete State Code들을 보면 알 수 있다.


단점 : 하나의 ConcreteState 역할이 다른 ConcreteState 역할을 알아야한다는 점이다. 엥?? 

아까는 장점이라매? 장난치나?? 라고 하실지도 모르겠군요..ㅋㅋ;;

즉, 상태변화를 ConcreteState역할에 맡겨버리면 클래스간의 의존관계를 강하게 만들기 때문에

위의 Class StateA에서 StateB의 객체를 만드는 부분이 있습니다. 이때 StateB가 삭제 되버리면

StateA에도 수정을 가해야하는 단점이 있습니다. 그래서 

Mediator Pattern을 적용 할 수 도 있을 것 같다. 


2013/12/09 - [Architecture/DesignPattern] - [DesignPattern] mediator pattern



- 끝 -










저작자 표시 비영리 변경 금지
신고

'Architecture > DesignPattern' 카테고리의 다른 글

[DesignPattern] Iterator pattern  (0) 2014.01.06
[DesignPattern] flyweight pattern  (0) 2014.01.06
[DesignPattern] state pattern  (0) 2013.12.31
[DesignPattern] memento pattern  (0) 2013.12.16
[DesignPattern] mediator pattern  (0) 2013.12.09
[DesignPattern] command pattern  (0) 2013.12.03

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] memento pattern

Architecture/DesignPattern 2013.12.16 01:31
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

The memento pattern is a software design pattern that provides the ability to restore an object to its previous state (undo via rollback).

The memento pattern is implemented with three objects: the originator, a caretaker and a memento.

The originator is some object that has an internal state. The caretaker is going to do something to the originator, but wants to be able to undo the change. The caretaker first asks the originator for a memento object. Then it does whatever operation (or sequence of operations) it was going to do. To roll back to the state before the operations, it returns the memento object to the originator. The memento object itself is an opaque object (one which the caretaker cannot, or should not, change). When using this pattern, care should be taken if the originator may change other objects or resources - the memento pattern operates on a single object.


출처) 위키피디아

 

memento pattern에는 3가지 객체가 필요하다.

1) originator

    originator

      미국·영국 [ərídƷənèitər] 발음듣기 영국식 발음듣기 다른 뜻(1건) 예문보기

      창작자, 창설자, 창시자, 발기인, 시조

      가. Sets and Gets values from the currently targeted memento object.

      나. Creates new Mementos and assigns current values to them.


2) caretaker

         caretaker

미국식 [|kerteɪkə(r)] / 영국식 [|keəteɪkə(r)]

1. (건물의) 경비원   2. (주택토지의) 관리인   3. 다른 사람을 돌보는 사람

Holds an ArrayList that contains all previous versions of the Memento.

It can store and retrieve stored Mementos.


3) menento

         memento 미국식 [mə|mentoʊ] 발음 듣기 영국식 [mə|mentəʊ] 발음 듣기 
(사람・장소를 기억하기 위한) 기념품 
: 기본 object로 다른 상태들을 저장 한다.


 memento pattern은 이전 상태의 객체를 쉽게 저장하는 방법 중에 하나이다.

 

즉, undo~!! 이전 상태로 돌리는 것이다. 이전 상태로 돌릴려면..어떻게?????

☞ 이전 상태의 오브젝트의 정보를 저장 해야한다.

   오브젝트의 정보를 복원하기 위해서는 자유자재로 해당 오브젝트를 액세스 할 수 있어야 할 것이다.

   하지만 이런식으로 오브젝트를 리플렉션을 하다가는 캡슐화가 보장받지 못하게 된다.

   그래서!! 캡슐화도 보장받고, 저장 및 이전상태로 돌리는(복원) undo를 가능케하는 것이 바로 memento pattern 인 것이다!(멋진데..)

  

 

     

Originator
- Originator는 자신의 현재 상태를 저장하고 싶을 때 Memento를 만든다.(createMemento) 또한, 이전의 Memento object를 전달받으면 그 Memento object를 만든 시점의 상태로 돌리는 처리를 실행한다.

 

package kr.pe.acet.memento;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
 
public class Gamer {
    private int money;
    private List<String> fruits = new ArrayList<String>();
    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){
            money += 100;
            System.out.println("소지금이 증가했습니다.");
        }else if(dice == 2){
            money /= 2;
            System.out.println("소지금이 절반이 되었습니다.");
        }else if(dice == 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){
        this.money = memento.money;
        this.fruits = memento.getFruits();
    }
    
    public String toString(){
        return "[money = " + money + ", fruits = " + fruits + "]";
    }
    
    private String getFruit(){
        String prefix = "";
        if(random.nextBoolean()){
            prefix = "맛있는 ";
        }
        
        return prefix + fruitsname[random.nextInt(fruitsname.length)];
    }
}

 

 

Memento의 역할
- Memento 역할은 Originator 역할의 내부 정보를 정리한다. Memento 역할은 Originator 역할의 내부 정보를 가지고 있지만, 그 정보를 누구에게도 공개하지 않는다. Memento 역할은 다음 두 종류의 인터페이스를 가지고 있다.

1. wide interface : Memento class에서 제공하는 이 인터페이스는 오브젝트의 상태를 원래의 상태로 돌리기 위해 필요한 정보를 모두 얻을 수 있는 메소드의 집합이다. 이 인터페이스는 Memento 역할의 내부상태를 속속들이 들어내기 때문에 이것을 사용하는 것은 Originator class 뿐이다.
2. narrow interface : Memento 역할이 제공하는 이 인터페이스는 외부의 Caretaker class에게 보여주는 것이다.

   이 인터페이스로 할 수 있는 일에는 한계가 있고 내부 상태가 외부에 공개되는 것을 방지한다.

이 두 종류의 인터페이스를 구별해서 사용하면 오브젝트의 캡슐화를 보장 받을 수 있다.

 

package kr.pe.acet.memento;

import java.util.ArrayList;
import java.util.List;
 
public class Memento {
    int money;
    ArrayList<String> fruits;
     
     public int getMoney(){    //narrow interface(외부의 Caretaker class에게 보여주는 것)
         return money;
     }
     
     Memento(int money){    //wide interface(오브젝트의 상태를 원래의 상태로 돌리기 위해..Originator class에서 접근)
         this.money = money;
         this.fruits = new ArrayList<String>();
     }
     
     void addFruit(String fruit){    //wide interface
         fruits.add(fruit);
     }
     
     @SuppressWarnings("unchecked")
     List<String> getFruits(){    //wide interface
         return (List<String>)fruits.clone();
     }
}

 

 

 Caretaker의 역할
- Caretaker 역할은 현재의 Originator 역할의 상태를 저장하고 싶을 때, 그것을 Originator 역할에게 전한다. Originator 역할은 그것을 받아서 Memento 역할을 만들어 Caretaker 역할에게 전달한다. Caretaker 역할은 미래의 필요에 대비해서 그 Memento 역할을 저장해 둔다.
Caretaker 역할은 Memento 역할이 갖는 2종류의 인터페이스중에서 narrow interface만 사용할 수 있으므로 Memento 역할의 내부 정보에 액세스할 수 없다. 

 

package kr.pe.acet.memento;

import static org.junit.Assert.*;

import org.junit.Test;

public class Caretaker {

 @Test
 public void careTakerTest() {
      Gamer gamer = new Gamer(100);                     // originator
      Memento memento = gamer.createMemento(); 
          
      for(int i = 0; i < 10; i++){
            System.out.println("==== " + i);
            System.out.println("현상 : " + gamer);  //  return "[money = " + money + ", fruits = " + fruits + "]"; 
              
            gamer.bet();
              
            System.out.println("소지금은 " + gamer.getMoney() + "원이 되었습니다.");
             
            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){
                 e.printStackTrace();
             }
              
             System.out.println("");
        }
 
 
 }

}

 

 

 

결과

==== 0
현상 : [money = 100, fruits = []]
과일(맛있는 포도)을 받았습니다.
소지금은 100원이 되었습니다.

==== 1
현상 : [money = 100, fruits = [맛있는 포도]]
변한 것이 없습니다.
소지금은 100원이 되었습니다.

==== 2
현상 : [money = 100, fruits = [맛있는 포도]]
소지금이 증가했습니다.
소지금은 200원이 되었습니다.
 (많이 증가했으므로 현재의 상태를 저장하자)

==== 3
현상 : [money = 200, fruits = [맛있는 포도]]
변한 것이 없습니다.
소지금은 200원이 되었습니다.

==== 4
현상 : [money = 200, fruits = [맛있는 포도]]
과일(귤)을 받았습니다.
소지금은 200원이 되었습니다.

==== 5
현상 : [money = 200, fruits = [맛있는 포도, 귤]]
변한 것이 없습니다.
소지금은 200원이 되었습니다.

==== 6
현상 : [money = 200, fruits = [맛있는 포도, 귤]]
변한 것이 없습니다.
소지금은 200원이 되었습니다.

==== 7
현상 : [money = 200, fruits = [맛있는 포도, 귤]]
변한 것이 없습니다.
소지금은 200원이 되었습니다.

==== 8
현상 : [money = 200, fruits = [맛있는 포도, 귤]]
변한 것이 없습니다.
소지금은 200원이 되었습니다.

==== 9
현상 : [money = 200, fruits = [맛있는 포도, 귤]]
변한 것이 없습니다.
소지금은 200원이 되었습니다. 

 Tip. 스택, 큐 등을 이용하여 히스토리로써 관리할 수도 있다. 또한 serialization을 통해서 파일로 관리하도록 기능을 확장할 수 있다. 

 

마지막으로 요 동영상은 꼭보자!

http://www.youtube.com/watch?v=jOnxYT8Iaoo


참고 사이트 : http://scotty83.tistory.com/entry/Memento-Pattern

 

      참고 사항

2013/11/24 - [Architecture/DesignPattern] - [DesignPattern] observer pattern

 

2013/11/24 - [Architecture/DesignPattern] - [DesignPattern] Interpreter pattern

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] singleton 패턴

 

2013/12/03 - [Architecture/DesignPattern] - [DesignPattern] command pattern

 

2013/12/09 - [Architecture/DesignPattern] - [DesignPattern] mediator pattern

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] abstractFactory 패턴

 

저작자 표시 비영리 변경 금지
신고

'Architecture > DesignPattern' 카테고리의 다른 글

[DesignPattern] flyweight pattern  (0) 2014.01.06
[DesignPattern] state pattern  (0) 2013.12.31
[DesignPattern] memento pattern  (0) 2013.12.16
[DesignPattern] mediator pattern  (0) 2013.12.09
[DesignPattern] command pattern  (0) 2013.12.03
[DesignPattern] observer pattern  (0) 2013.11.24

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] mediator pattern

Architecture/DesignPattern 2013.12.09 20:26
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

 

2013/12/03 - [Architecture/DesignPattern] - [DesignPattern] command pattern

 

2013/11/24 - [Architecture/DesignPattern] - [DesignPattern] observer pattern

 

2013/11/24 - [Architecture/DesignPattern] - [DesignPattern] Interpreter pattern

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] singleton 패턴

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] abstractFactory 패턴

 

 

<< Mediator Pattern >>

 

패턴의 의도 : 각 객체가 관련성을 갖는 다른 객체에 대한 참조관계를 직접 정의하기 보다는 이를 독립된 다른 객체가 관리..(-_-;;뭥미?)

즉, 중재한다고 보면 된다^-^

 

아래의 소스는 비행기를 예를 들었는데 너무 좋은 예인것 같다.

비행기들이 서로 충돌하지 않고 착륙 한다. 어떻게?? 관제탑이 비행기들을 중재하기 때문이다.

즉, 비행기끼리 서로 통신한다면 매우 혼란을 겪게 된다.


ex) 그림을 하나 보자

아래처럼 비행기들 끼리 서로 통신을 한다면 복잡스러울 것이다. 지금은 4대라서 6번이지만..ㅋㅋ



그래서 관제탑을 두어서 관리하면 아래와 같이 깔끔하다. 굳~!

 


Colleague : Mediator와 통신하는 객체들이라고 생각하시면 됩니다

            colleague

           미국식 [|kɑ:li:g] 발음듣기 영국식 [|kɒli:g] 발음듣기

            (같은 직장이나 직종에 종사하는) 동료

 

           핵심 문장!! : "Mediator 는 모든 것을 알고 있다+ㅁ+"

           즉,  tower.land(this);  <---Colleague에서 Mediator Pattern의 객체를 받아서 해당 method를 호출 한다.

           이미 Mediator는 task가 정해져있고 그 task를 실제로 하는 아이들이 Colleague 들이다.

     그런 의미에서 Mediator가 Colleague들을 중재한다고 볼 수 있다.


위를 이해했다면 Facade 패턴과 Mediator 패턴의 차이를 알 수가 있다.

Facade패턴은 창구라고 생각하면 되니 창구안의 객체들을 중재하는 기능은 없다.

하지만 Mediator는 이미 모든것을 정해놓고 Colleague, Mediator와 통신하는 객체들이기때문에 중재를 한다.

헷깔리지 말자~!^-^good~

 

아래의 소스에서 조금 아쉬운 것은 Colleague가 Interface 구조가 아니라는 것이다. Mediator가 하나 일 수 있지만 Colleague가 여러가지 일 경우가 많을 것이다. 물론 Mediator 또한 Interface로 갈 수 있다.(아래의 소스에 그렇게 해놨다..ㅋㅋㅋ 하지만 의미는 없다는거;;)

암튼 이해하기에는 좋은 소스임에는 틀림이 없다.


UML을 보자! - Class Diagram을 보자. 손수 그렸다..ㅋㅋ;;

또는 아래에는 표현이 되어있지는 않지만 Mediator를 Colleague에서 연관시켜서 

setMediator 로 받아서 또 다른 Mediator 사용도 가능하다.



main source

package kr.pe.acet.mediator;

public class MediatorMain {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  ControlTower tower = new ControlTower();
  
  Airplane[] airplanes = new Airplane[10]; // Colleague
  for (int i = 0; i < airplanes.length; i++) {
   airplanes[i] = new Airplane(tower, i);
  }
  for (Airplane airplane : airplanes) {
   airplane.start();
  }

 }

}
 

 

colleague source : Airplane

 package kr.pe.acet.mediator;

public class Airplane extends Thread {
    private final ControlTower tower;
    private final int seq;

    public Airplane(ControlTower tower, int seq) {
        this.tower = tower;
        this.seq = seq;
    }

    public int getSeq() {
        return seq;
    }

    @Override
    public void run() {
        try {
            while (!tower.getPermission()) {
                System.out.println(seq +"번 째 비행기 대기 중.");
                Thread.sleep(10L);
            }
            tower.land(this);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

mediator interface

 package kr.pe.acet.mediator;

public interface MediatorControlTower {
   public boolean getPermission();
   public void land(Airplane airplane) throws InterruptedException;
}

 

concreate Mediator

 package kr.pe.acet.mediator;

public class ControlTower implements MediatorControlTower{
    private volatile  boolean inUse;
   
    public synchronized boolean getPermission(){
        if (inUse) {
            return false;
        }else{
            inUse = true;
            return true;
        }
    }
   
    public void land(Airplane airplane) throws InterruptedException{
        int seq = airplane.getSeq();
        System.out.println(seq +"번 비행기 착륙 시작");
        Thread.sleep(50L);
        System.out.println(seq + "번 비행기 착륙 끝");
        inUse = false;
    }
}

 

 결과 - 쫌 길다..ㅋㅋㅋ 

1번 비행기 착륙 시작
3번 째 비행기 대기 중.
5번 째 비행기 대기 중.
0번 째 비행기 대기 중.
6번 째 비행기 대기 중.
2번 째 비행기 대기 중.
4번 째 비행기 대기 중.
7번 째 비행기 대기 중.
9번 째 비행기 대기 중.
8번 째 비행기 대기 중.
3번 째 비행기 대기 중.
5번 째 비행기 대기 중.
9번 째 비행기 대기 중.
6번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
8번 째 비행기 대기 중.
4번 째 비행기 대기 중.
7번 째 비행기 대기 중.
5번 째 비행기 대기 중.
3번 째 비행기 대기 중.
2번 째 비행기 대기 중.
4번 째 비행기 대기 중.
6번 째 비행기 대기 중.
0번 째 비행기 대기 중.
9번 째 비행기 대기 중.
7번 째 비행기 대기 중.
8번 째 비행기 대기 중.
5번 째 비행기 대기 중.
3번 째 비행기 대기 중.
7번 째 비행기 대기 중.
4번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
6번 째 비행기 대기 중.
8번 째 비행기 대기 중.
9번 째 비행기 대기 중.
5번 째 비행기 대기 중.
3번 째 비행기 대기 중.
9번 째 비행기 대기 중.
8번 째 비행기 대기 중.
6번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
4번 째 비행기 대기 중.
1번 비행기 착륙 끝
3번 비행기 착륙 시작
5번 째 비행기 대기 중.
2번 째 비행기 대기 중.
6번 째 비행기 대기 중.
9번 째 비행기 대기 중.
8번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
4번 째 비행기 대기 중.
5번 째 비행기 대기 중.
6번 째 비행기 대기 중.
4번 째 비행기 대기 중.
8번 째 비행기 대기 중.
9번 째 비행기 대기 중.
2번 째 비행기 대기 중.
7번 째 비행기 대기 중.
0번 째 비행기 대기 중.
5번 째 비행기 대기 중.
4번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
8번 째 비행기 대기 중.
9번 째 비행기 대기 중.
6번 째 비행기 대기 중.
0번 째 비행기 대기 중.
5번 째 비행기 대기 중.
9번 째 비행기 대기 중.
2번 째 비행기 대기 중.
6번 째 비행기 대기 중.
4번 째 비행기 대기 중.
7번 째 비행기 대기 중.
8번 째 비행기 대기 중.
0번 째 비행기 대기 중.
5번 째 비행기 대기 중.
9번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
4번 째 비행기 대기 중.
6번 째 비행기 대기 중.
8번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
3번 비행기 착륙 끝
9번 비행기 착륙 시작
6번 째 비행기 대기 중.
4번 째 비행기 대기 중.
7번 째 비행기 대기 중.
0번 째 비행기 대기 중.
8번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
0번 째 비행기 대기 중.
6번 째 비행기 대기 중.
7번 째 비행기 대기 중.
4번 째 비행기 대기 중.
8번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
6번 째 비행기 대기 중.
8번 째 비행기 대기 중.
4번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
6번 째 비행기 대기 중.
0번 째 비행기 대기 중.
4번 째 비행기 대기 중.
7번 째 비행기 대기 중.
8번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
6번 째 비행기 대기 중.
8번 째 비행기 대기 중.
7번 째 비행기 대기 중.
4번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
9번 비행기 착륙 끝
0번 째 비행기 대기 중.
8번 째 비행기 대기 중.
7번 째 비행기 대기 중.
6번 째 비행기 대기 중.
4번 비행기 착륙 시작
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
0번 째 비행기 대기 중.
6번 째 비행기 대기 중.
7번 째 비행기 대기 중.
8번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
6번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
8번 째 비행기 대기 중.
5번 째 비행기 대기 중.
6번 째 비행기 대기 중.
7번 째 비행기 대기 중.
8번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
6번 째 비행기 대기 중.
7번 째 비행기 대기 중.
8번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
7번 째 비행기 대기 중.
6번 째 비행기 대기 중.
4번 비행기 착륙 끝
8번 비행기 착륙 시작
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
7번 째 비행기 대기 중.
6번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
7번 째 비행기 대기 중.
6번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
7번 째 비행기 대기 중.
6번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
5번 째 비행기 대기 중.
6번 째 비행기 대기 중.
2번 째 비행기 대기 중.
7번 째 비행기 대기 중.
0번 째 비행기 대기 중.
5번 째 비행기 대기 중.
8번 비행기 착륙 끝
6번 비행기 착륙 시작
2번 째 비행기 대기 중.
7번 째 비행기 대기 중.
5번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
5번 째 비행기 대기 중.
2번 째 비행기 대기 중.
7번 째 비행기 대기 중.
5번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
5번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
5번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
6번 비행기 착륙 끝
5번 비행기 착륙 시작
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
7번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
2번 째 비행기 대기 중.
0번 째 비행기 대기 중.
5번 비행기 착륙 끝
7번 째 비행기 대기 중.
2번 비행기 착륙 시작
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
7번 째 비행기 대기 중.
0번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
0번 째 비행기 대기 중.
7번 째 비행기 대기 중.
7번 째 비행기 대기 중.
0번 째 비행기 대기 중.
2번 비행기 착륙 끝
0번 비행기 착륙 시작
7번 째 비행기 대기 중.
7번 째 비행기 대기 중.
7번 째 비행기 대기 중.
7번 째 비행기 대기 중.
7번 째 비행기 대기 중.
7번 째 비행기 대기 중.
0번 비행기 착륙 끝
7번 비행기 착륙 시작
7번 비행기 착륙 끝

 



참고 사이트 : http://iilii.egloos.com/4850510 

                     http://www.youtube.com/watch?v=jWF6dvSr_Pk


- 끝 -


저작자 표시 비영리 변경 금지
신고

'Architecture > DesignPattern' 카테고리의 다른 글

[DesignPattern] state pattern  (0) 2013.12.31
[DesignPattern] memento pattern  (0) 2013.12.16
[DesignPattern] mediator pattern  (0) 2013.12.09
[DesignPattern] command pattern  (0) 2013.12.03
[DesignPattern] observer pattern  (0) 2013.11.24
[DesignPattern] Interpreter pattern  (0) 2013.11.24

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] command pattern

Architecture/DesignPattern 2013.12.03 19:48
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

 

2013/11/24 - [Architecture/DesignPattern] - [DesignPattern] observer pattern

 

2013/11/24 - [Architecture/DesignPattern] - [DesignPattern] Interpreter pattern

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] abstractFactory 패턴

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] singleton 패턴

 

금일은 Command Pattern 에 대해서 스터디를 했네요^^

reo형님이 빠져서 아쉽네요..ㅜㅜ..지못미..


출처 : http://ko.wikipedia.org/wiki/%EC%BB%A4%EB%A7%A8%EB%93%9C_%ED%8C%A8%ED%84%B4

커맨드 패턴(Command pattern)이란 요청을 객체의 형태로 캡슐화하여 서로 요청이 다른 사용자의 매개변수와, 요청 저장 또는 로깅, 그리고 연산의 취소를 지원하게 만드는 패턴이다.


라고~위키피디아에 명시 되어져있습니다.


 

 

 

 

소스 : command.zip

 

테스트 코드 : CommandTest.java

 

저작자 표시 비영리 변경 금지
신고

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] observer pattern

Architecture/DesignPattern 2013.11.24 23:10
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

 

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] singleton 패턴

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] abstractFactory 패턴

 

2013/11/24 - [Architecture/DesignPattern] - [DesignPattern] Interpreter pattern

 

 

참조 사이트 :

http://ko.wikipedia.org/wiki/%EC%98%B5%EC%84%9C%EB%B2%84_%ED%8C%A8%ED%84%B4

 

11월 25일 내부 스터디(일명: 용수철 스터디 그룹!)

observer pattern에 대해서 알아보자^^

객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용된다. 발행/구독 모델로 알려져 있기도 하다.

 

이 패턴의 핵심은 옵서버 또는 리스너(listener)라 불리는 하나 이상의 객체를 등록하거나 자신을 등록시킨다. 그리고 관찰되는 객체(또는 주제)에서 발생하는 이벤트를 전달한다.

 

구조는 아래와 같디.

 

 

 

소스 - 패키지는 package kr.pe.acet.observer; 이다~~

 

EventSource.java

 

MyApp.java

 

ResponseHandler.java

소스가 쓰레드 형태라서..JUnit으로는 동작하지 않아서 아쉽다..ㅋㅋ; 사실 동작하지 않는 것인지..동작 못시키는건지...@-@;;

 

Test 소스

 

ObserverPatternTest.java

저작자 표시 비영리 변경 금지
신고

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[소프트웨어 아키텍처 이론과 실체] 아키텍트로 가기 위한 필독서!!

Architecture/AA 2013.11.24 22:59
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

 

소프트웨어 아키텍처 이론과 실체

라는 책을 산지..올해 2월에 산것 같은데..제대로 보지를 못했다..ㅠ_ㅠ 채수원님 책은 술술 읽혀서 보았다 다행히..

2013/03/05 - [Life of AceT/Good book] - 소프트웨어 아키텍처 이론과 실제, TDD(채수원)

 

아직 기초 지식이 부족하여 할 것이 너무나도 많다..(아~내 잃어버린 시간들이여~~진작에 공부를 했어야..쿨럭~)

조금 정리를 하여 조금씩 이라도 볼 생각이다.

사실 잊고 있었는데..홍K(前팀장)님이..자극을 주셨다+ㅁ+~고오오오오오~

좋은 자료도 주시고..흐흐+ㅁ+흐흐흐~나만 봐야디~

 

자!~ 책의 구성은 총 4부로 되어있다. 혼자보기에는 엄청 힘들 것 같기도 하다..ㄷㄷㄷ

1부. 아키텍처의 개요

   1장) 아키텍처 비즈니스 사이클

   2장) 소프트웨어 아키텍처 정의

   3장) A-7E 항공 전자 시스템

 

2부. 아키텍처 수립

   4장) 품질속성 이해

   5장) 품질 목표 달성

   6장)항공관제 시스템

   7장) 아키텍처 설계

   8장) 비행 모의실험

   9장) 아키텍처 문서화

   10장) 아키텍처 재건

 

3부. 아키턱처 분석

   11장) ATAM

   12장) CBAM

   13장) 월드와이드웹

 

 4부. 아키텍처 확산

   14장) 소프트웨어 프로덕트 라인

   15장) 셀시우스테크

   16장) J2EE/EJB

   17장) 루더 아키텍처

   18장) 기성 컴포넌트를 활용한 시스템 구축

   19장) 소프트웨어 아키텍처의 미래

 

 

 

 

 

 

저작자 표시 비영리 변경 금지
신고

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::

[DesignPattern] Interpreter pattern

Architecture/DesignPattern 2013.11.24 22:41
[Good Comment!!, Good Discussion!!, Good Contens!!]
[ If you think that is useful, please click the finger on the bottom~^-^good~ ]
by ace-T

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] singleton 패턴

 

2013/07/21 - [Architecture/DesignPattern] - [첫번째 스터디] abstractFactory 패턴

지금까지 공부 한 디자인 패턴 목록

  : http://acet.pe.kr/notice/325

 

음..정리는 2개뿐이 하질 않았군요.. 하하;;

 

프로젝트와 병행을 하고 있어서..11월 19일부터 내부 스터디 다시 시작 합니다^-^/

 

매주 월요일 - 눈이 오나 비가오나 지구가 망해도 스터디는 진행 합니다. 아무도 참여하지 않아도 진도는 나갑니다.ㅋㅋㅋㅋ

 

<< 2013년 11월 19일 >>

범 위  : Interperter 패턴

참여 인원 : 4명 중 3명 참여

  참 여 : 공K, 박D, Mr. 권

  불 참 : 이D(교육 참여)

 

참고 사이트 : http://ko.wikipedia.org/wiki/%EC%98%B5%EC%84%9C%EB%B2%84_%ED%8C%A8%ED%84%B4

 

인터프리터 패턴 이란??

In computer programming, the interpreter pattern is a design pattern that specifies how to evaluate sentences in a language.

위의 빨간 문장이 어떻게 보면 핵심인 것 같다. 영어라서 그런지..해석해보면 Interpreter가 뭔지 잘 모르면

난감 할 수 있는 문장이다.

evaluate를 네이버에서 찾아보면 아래와 같다 ㅋㅋ

더보기

 

 암튼 해석을 해보면 어떤 특별한(상징적인) 문장을 평가(해석)한다는 뜻이다.

 

The basic idea is to have a class for each symbol (terminal or nonterminal) in a specialized computer language. The syntax tree of a sentence in the language is an instance of the composite pattern and is used to evaluate (interpret) the sentence

 

syntax tree 라는 것은 예를 들어서 a b + c a - -  이런 상징적인 녀석들이 모여서 차례차례 수행이 되는데

      syntax tree라는 용어를 사용 한다. 소스에서 syntax tree라는 변수가 있으니 그 용도를 보면 알 것 이다.

구조를 살펴보도록 하자! 

 

 

 

소스 -  패키지는 package kr.pe.acet.interpreter; 이다.

 

InterpreterPatternTest.java

 

Evaluator.java

 

Expression.java

 

Minus.java

 

Number.java

 

Plus.java

 

Variable.java

 

저작자 표시 비영리 변경 금지
신고

acet 박태하가 추천하는 readtrend 추천글!

설정

트랙백

댓글

:::: facebook을 이용하시는 분들은 로그인 후 아래에 코멘트를 남겨주세요 ::::