質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

820閲覧

StateパターンでStateクラスを作る意味とは

Udomomo

総合スコア1524

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

4クリップ

投稿2017/12/10 09:14

マーチン・ファウラー氏の「リファクタリング」の本を読んでいるのですが、Stateパターンを使ってリファクタリングする例が載っていました。
それをふまえて自分でも考えてみたのですが、なぜ親クラスと子クラスの間にStateクラスを作るのか、その意義がぴんときていません。

例えばPythonの場合、gitHubに載っていたコードでは、継承関係は Radio - State - AMState/FMState となっています。

Python

1""" http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/""" 2 3 4class State(object): 5 """Base state. This is to share functionality""" 6 7 def scan(self): 8 """Scan the dial to the next station""" 9 self.pos += 1 10 if self.pos == len(self.stations): 11 self.pos = 0 12 print("Scanning... Station is", self.stations[self.pos], self.name) 13 14 15class AmState(State): 16 def __init__(self, radio): 17 self.radio = radio 18 self.stations = ["1250", "1380", "1510"] 19 self.pos = 0 20 self.name = "AM" 21 22 def toggle_amfm(self): 23 print("Switching to FM") 24 self.radio.state = self.radio.fmstate 25 26 27class FmState(State): 28 def __init__(self, radio): 29 self.radio = radio 30 self.stations = ["81.3", "89.1", "103.9"] 31 self.pos = 0 32 self.name = "FM" 33 34 def toggle_amfm(self): 35 print("Switching to AM") 36 self.radio.state = self.radio.amstate 37 38class Radio(object): 39 """A radio. It has a scan button, and an AM/FM toggle switch""" 40 def __init__(self): 41 """We have an AM state and an FM state""" 42 self.amstate = AmState(self) 43 self.fmstate = FmState(self) 44 self.state = self.amstate 45 46 def toggle_amfm(self): 47 self.state.toggle_amfm() 48 49 def scan(self): 50 self.state.scan() 51 52# Test our radio out 53if __name__ == '__main__': 54 radio = Radio() 55 actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2 56 actions *= 2 57 58 for action in actions: 59 action()

これを以下のように書き換えても、全く同じように動作しました。
クラスの継承関係を、Radio - AMState/FMStateというように、Stateを挟まない形に変えたものです。

Python

1class Radio(object): 2 """A radio. It has a scan button, and an AM/FM toggle switch""" 3 def __init__(self): 4 """We have an AM state and an FM state""" 5 self.amstate = AmState(self) 6 self.fmstate = FmState(self) 7 self.state = self.amstate 8 9 def toggle_amfm(self): 10 self.state.toggle_amfm() 11 12 def scan(self): 13 self.state.scan() 14 15 16class AmState(Radio): 17 def __init__(self, radio): 18 self.radio = radio 19 self.stations = ["1250", "1380", "1510"] 20 self.pos = 0 21 self.name = "AM" 22 23 def toggle_amfm(self): 24 print("Switching to FM") 25 self.radio.state = self.radio.fmstate 26 27 def scan(self): 28 """Scan the dial to the next station""" 29 self.pos += 1 30 if self.pos == len(self.stations): 31 self.pos = 0 32 print("Scanning... Station is", self.stations[self.pos], self.name) 33 34 35class FmState(Radio): 36 def __init__(self, radio): 37 self.radio = radio 38 self.stations = ["81.3", "89.1", "103.9"] 39 self.pos = 0 40 self.name = "FM" 41 42 def toggle_amfm(self): 43 print("Switching to AM") 44 self.radio.state = self.radio.amstate 45 46 def scan(self): 47 """Scan the dial to the next station""" 48 self.pos += 1 49 if self.pos == len(self.stations): 50 self.pos = 0 51 print("Scanning... Station is", self.stations[self.pos], self.name) 52 53# Test our radio out 54if __name__ == '__main__': 55 radio = Radio() 56 actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2 57 actions *= 2 58 59 for action in actions: 60 action()

このため、なぜStateパターンでは後者でなく前者のようにするのかがよくわかりません。
Javaであれば言語特性上、話が違ってくるのかもしれませんが...
どのような意義があるのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Javaであれば言語特性上、話が違ってくるのかもしれませんが...

はい、Javaでは複数のStateを共通して扱うために、親クラスもしくはインターフェースを用意する必要があります。

Pythonなどでは、同じメソッドを持たせることでダックタイピング可能ですので、そのまま各Stateがばらばらにある形でも問題ありません。

投稿2017/12/10 10:43

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Udomomo

2017/12/12 00:24

ありがとうございます。やはりそうなんですね。 回答を機に自分でも調べて、静的型付け言語と動的型付け言語の違い、抽象クラスやインターフェースの意義など、いろいろ学ぶことができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問