## State
> 讓物件的外顯行為隨內部狀態的改變而改變,彷彿連類別也變了似的
### 時機
* 當物件行為取決於它的狀態,連執行期行為也得隨狀態而改變時。
* 若是某些操作內,依據物件狀態而做的條件判斷式太過龐大時。
### 結構

### 參與者
* Context
-制定外界改興趣的介面
-持有一個ConcreteState子類別的物件個體,代表現行狀態
* State
-此介面負責封裝當Context處於特定狀態時所該展現的行為
* ConcreteState
-每一個子類別都針對某一種Context狀態實作出該展現的行為
```ruby=
class Context
attr_accessor :state
private :state
def initialize(state)
transition_to(state)
end
def transition_to(state)
puts "Context: Transition to #{state.class}"
@state = state
@state.context = self
end
def request1
@state.handle1
end
def request2
@state.handle2
end
end
class State
attr_accessor :context
def handle1
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
def handle2
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
end
class ConcreteStateA < State
def handle1
puts 'ConcreteStateA handles request1.'
puts 'ConcreteStateA wants to change the state of the context.'
@context.transition_to(ConcreteStateB.new)
end
def handle2
puts 'ConcreteStateA handles request2.'
end
end
class ConcreteStateB < State
def handle1
puts 'ConcreteStateB handles request1.'
end
def handle2
puts 'ConcreteStateB handles request2.'
puts 'ConcreteStateB wants to change the state of the context.'
@context.transition_to(ConcreteStateA.new)
end
end
# The client code.
context = Context.new(ConcreteStateA.new)
context.request1
context.request2
```
### 合作方式
* Context將與狀態有關的訊息委託給目前持的ConcreteState物件去處理
* Context把自己列為參數,傳給處理訊息的State物件,以便後者在必要時能存取得到自己
* Context是主要的對外窗口。客戶碼可用State物件來設定Context組態,設定好後,就不在直接插手State物件
* 可令Context或者ConcreteState的子類別決定在什麼情況下該切換成什麼狀態
### 優點
1. 集中處理與狀態相依的行為並予以切割(易於新增狀態)。也可以使用資料值的方式儲存,但會造成許多判斷式。
2. 凸顯狀態轉移邏輯。以Context的角度來看,狀態轉移應該是不可再細分的atomic動作;觀念上應該是重設**一個**變數(Context的State物件變數),不該是好幾個變數設來設去。
3. 狀態物件可以共用。如果State物件不含個體變數,Context就可共用State物件(此時State物件就相當於沒有內在狀態或者說只有行為的Flyweight物件)