考えてみてください:ある関数を実現するためのアルゴリズムや戦略は複数存在する可能性があり、条件に基づいて関数を完成させるために適切なアルゴリズムや戦略を選択する必要があります。例えば、ソートアルゴリズムには、バブルソート、サブサンプションソート、クイックソートなどを使うことができます。どのように実装しますか?
多くの生徒が、各メソッドがソート・アルゴリズムであるクラスを書きたいと考え、そしてif.....else... .else...と書いてどのアルゴリズムを使うかを決定し、対応するメソッドを呼び出します。明らかにこれではクラスが肥大化してしまいますし、ヒープソートのようなアルゴリズムを追加したい場合は、それにメソッドを追加して、どのアルゴリズムを使うかを判断して対応するメソッドを呼び出すために、if... .else.....else... これはオープン/クローズの原則と単一責任の原則に対する明らかな違反です。
本日ご紹介するストラテジー・パターンは、このニーズをエレガントに満たすものです。
定義
strategyパターンは一連のアルゴリズムを定義し、それぞれが交換可能なようにカプセル化します。strategyパターンでは、アルゴリズムを使用するクライアントとは無関係にアルゴリズムを変更することができます。
シナリオ
- 同じタイプの問題に対する複数のアプローチ。
- 同じ型の複数の操作を安全にカプセル化する必要がある場合
- 同じ抽象クラスのサブクラスが複数あり、if-else や switch-case を使って具象実装を選択する必要がある場合
UML
- Context 政策が運用される背景。
- Stragety ストラテジーの抽象化
- 具体的戦略A、具体的戦略B 具体的戦略の実施
実装
- 必要なアルゴリズムやコードブロックをインターフェースや抽象クラスに抽象化
- このアルゴリズム・インターフェースのメンバ変数とセッタを元のクラスに追加します。
- アルゴリズム・インターフェースはいくつかの方法で実装されています。
東漢末期、三国に分かれ、烽火は絶えることなく燃え続けました。
周瑜は劉備を美女と一緒に捕まえて、荊州と交換しようと考えました。
諸葛亮は趙雲に護衛を頼み、それに対処するために3つの袋を持ってきました。
この3つの錦袋がそれに対処するための戦略であることは明らかで、なぜ錦袋に入っていて趙雲に教えていないかというと、諸葛亮はベテランのプログラマーとしてディミトリの法則をよく知っているからです。趙雲はただ袋を開け、適切なタイミングで実行すればよかったのです。
Shut up and show me the code
Tapestry Interface - ポリシーの抽象化
interface Strategy {
fun name(): String
// アルゴリズム戦略メソッド
fun algorithm()
}
つのヒント - 具体的な戦略
class StrategyFirst : Strategy {
override fun name(): String {
return "トリックの最初の袋"
}
override fun algorithm() {
println("年老いた喬に敬意を表し、劉備の結婚を東呉のすべての人々に知らせたい」)。
}
}
class StrategySecond : Strategy {
override fun name(): String {
return "トリックの第二の袋"
}
override fun algorithm() {
println("あなたは嘘を使って、優しい場所にいる劉備を騙して荊州に戻らせることができる」)。
}
}
class StrategyThird : Strategy {
override fun name(): String {
return "トリックの3番目の袋"
}
override fun algorithm() {
println("孫尚香に呉の追っ手を鎮めさせる。 彼女は孫権の妹で、呉の将軍たちは彼女を恐れている」)。
}
}
長山趙子龍 - 戦略実行者
class Context(val name: String) {
var strategy: Strategy? = null
fun doStrategy() {
println("$name をオンにする ${strategy?.name()}:")
strategy?.algorithm()
}
}
アクション! 監督が撮影開始、諸葛亮が脚本家
fun main() {
val childDragon = Context("趙雲")
// 東武の最初の錦袋を開く
println("趙雲は命令を受け、劉備を500人の兵士とともに東呉まで護衛した。彼が南匈奴に到着したとき」)。
childDragon.strategy = StrategyFirst()
childDragon.doStrategy()
println("呉夫人は劉備に会い、結婚に同意し、結婚を実現させる
")
// 年末にセカンドバッグを開く
println("劉備新婚新婚旅行、荊州に戻ることを忘れて、趙雲数回無駄に、年末に")。
childDragon.strategy = StrategySecond()
childDragon.doStrategy()
println("翌日、孫尚香は先祖とともに荊州に逃げ込んだ。
")
// 第三の袋は、追っ手に逃げ道がないときに開けられる。
println("周瑜は追いつき、道をふさぐために軍隊を送った」)。
childDragon.strategy = StrategyThird()
childDragon.doStrategy()
println("孫尚香は怒って追っ手を叱責し、周瑜が追いつくように道を作ったが、関尔志が援軍を連れて到着した。
")
}
いよいよ劇場へ。
Androidのソースコードに適用
TimeInterpolator TimeInterpolator , 経過時間のパーセンテージに基づいて現在の属性値のパーセンテージを計算します。システムによって提供されます:
- 線形補間
- 线性插值器 LinearInterpolator
- 加速減速インターポレータ
そして最後に
戦略パターンをうまく使えば、あなたは「諸葛の再知」のプログラマーです。