目的
定義一整族演算法,將每一個演算法封裝起來,可互換使用,更可在不影響外界的情況下個別抽換所引用的演算法。
Define a family of algorithms, encapsulate each one, & make them interchangeable to let clients & algorithms vary independently.
適用
- 當需要同一演算法的各種變形版本時,可以自由切換行為。
- 演算法可以被封裝,讓外界不知道複雜的資料結構。
- 可以用一個interface合併所有不同行為的封裝為同一類別。
結構及成員
Collaborations: Strategy和Context協議出該採用的演算法版本。Context餵給Strategy會用到的資料(也可能把自己傳給Strategy)。Client通常會先建一個ConcreteStrategy餵給Context,之後Client就和Context打交道,Context會將Client傳來的訊息轉傳給Strategy。
影響結果
好處
壞處
實作
制訂Strategy和Context介面
Strategy和Context介面必須提供有效率的存取介面,讓ConcreteStrategy和Context互相存取必要資訊。
- 做法一:Context主動傳遞資料給Strategy,降低耦合,但也可能送出Strategy不需要的資料。
- 做法二:Context把自己當作傳參傳給Strategy,但耦合較高。
Strategy物件可有可無
Context可在存取Strategy之前先檢查在不在,在就使用;不在就依預設做法進行,這樣Context就不必處理任何Strategy物件。
方便vs隨便
因為可以很方便的轉換到另一個Strategy,所以要設有限制,才不會方便當隨便(如:人類walk變成fly)。
Example: Vehicle
//Class: Vehicle
package vehicle.go;
public abstract class Vehicle {
private GoAlgorithm algorithm;
public void setGoAlgorithm(GoAlgorithm algorithm) {
this.algorithm = algorithm;
}
public void go() {
algorithm.go();
}
}
//Class: StreetRacer
package vehicle.go;
public class StreetRacer extends Vehicle {
public StreetRacer() {
setGoAlgorithm(new GoByDriving());
}
}
//Class: FormulaOne
package vehicle.go;
public class FormulaOne extends Vehicle {
public FormulaOne() {
setGoAlgorithm(new GoByDriving());
}
}
//Class: Helicopter
package vehicle.go;
public class Helicopter extends Vehicle {
public Helicopter() {
setGoAlgorithm(new GoByFlying());
}
}
//Class: Jet
package vehicle.go;
public class Jet extends Vehicle {
public Jet() {
setGoAlgorithm(new GoByFlyingFast());
}
}
//Class: GoAlgorithm
package vehicle.go;
public interface GoAlgorithm {
public void go();
}
//Class: GoByDriving
package vehicle.go;
public class GoByDriving implements GoAlgorithm {
public void go() {
System.out.println("Now I'm driving.");
}
}
//Class: GoByFlying
package vehicle.go;
public class GoByFlying implements GoAlgorithm {
public void go() {
System.out.println("Now I'm flying.");
}
}
//Class: GoByFlyingFast
package vehicle.go;
public class GoByFlyingFast implements GoAlgorithm {
public void go() {
System.out.println("Now I'm flying fast.");
}
}
//Class: Main
package vehicle.go;
public class Main {
public static void main(String[] args) {
StreetRacer streetRacer = new StreetRacer();
FormulaOne formulaOne = new FormulaOne();
Helicopter helicopter = new Helicopter();
Jet jet = new Jet();
streetRacer.go();
formulaOne.go();
helicopter.go();
jet.go();
Jet realJet = new Jet();
realJet.setGoAlgorithm(new GoByDriving());
realJet.go();
realJet.setGoAlgorithm(new GoByFlyingFast());
realJet.go();
realJet.setGoAlgorithm(new GoByDriving());
realJet.go();
}
}
Result:
Now I'm driving.
Now I'm driving.
Now I'm flying.
Now I'm flying fast.
Now I'm driving.
Now I'm flying fast.
Now I'm driving.