序言
??都畢業(yè)好幾年了,對(duì)于設(shè)計(jì)模式剖效,平時(shí)也偶爾接觸過嫉入,但卻沒有系統(tǒng)的學(xué)習(xí)過,自然在遇到問題找解決方案的時(shí)候璧尸,也很少能想到設(shè)計(jì)模式咒林,感覺總是一種模糊的狀態(tài),所以爷光,準(zhǔn)備重寫梳理一下垫竞。
注:本系列設(shè)計(jì)模式相關(guān)代碼,開發(fā)語言使用Java蛀序,JDK版本基于1.8件甥。
概述
??策略模式是屬于一種行為型的設(shè)計(jì)模式,針對(duì)的是算法哼拔。我們可以通俗的理解為,策略模式就是對(duì)某一行為瓣颅,能根據(jù)不同的實(shí)現(xiàn)倦逐,完成相同的功能。比如排序宫补,我們能根據(jù)不同的類型檬姥,調(diào)用不同的實(shí)現(xiàn),來實(shí)現(xiàn)相同的功能粉怕,就是排序健民。
實(shí)現(xiàn)
策略模式中涉及到三個(gè)角色:
- Context角色:持有一個(gè)Strategy角色的引用;
- Strategy(抽象策略)角色:該角色通常是接口或抽象類贫贝;
- ConcreteStrategy(具體策略)角色:實(shí)現(xiàn)了抽象策略角色的算法秉犹。
實(shí)例
??我們拿一個(gè)例子來加深對(duì)策略模式的了解。比如大家出去旅游稚晚,可以選擇開火車崇堵,也可以選擇騎自行車,也可以選擇做汽車客燕。這其實(shí)就是一種策略模式的應(yīng)用鸳劳。
Strategy角色
public interface Strategy {
void travel();
}
抽象角色,只有一個(gè)方法也搓,就是出行的方法赏廓。
ConcreteStrategy具體策略
選擇坐汽車出去玩:
public class CarStrategy implements Strategy{
@Override
public void travel() {
System.out.println("--做汽車出去玩--");
}
}
選擇騎自行車出去玩:
public class BikeStrategy implements Strategy{
@Override
public void travel() {
System.out.println("--騎自行車出去玩--");
}
}
選擇坐火車出去玩:
public class TrainStrategy implements Strategy{
@Override
public void travel() {
System.out.println("--坐火車出去玩--");
}
}
Context角色
出去玩的對(duì)象是人:
public class PersonContext {
private Strategy strategy;
public PersonContext(Strategy strategy) {
this.strategy = strategy;
}
public void travel() {
strategy.travel();
}
}
ClientTest
public class ClientTest {
public static void main(String[] args) {
PersonContext personContext = new PersonContext(new BikeStrategy());
personContext.travel();
personContext = new PersonContext(new TrainStrategy());
personContext.travel();
}
}
打印結(jié)果:
--騎自行車出去玩--
--坐火車出去玩--
??這時(shí)候如果說涵紊,這時(shí)候出行的方式要改為坐輪船,其實(shí)這就相當(dāng)于更改策略幔摸,那我們?cè)賹?shí)現(xiàn)一個(gè)類摸柄,然后再調(diào)用的時(shí)候想辦法把參數(shù)傳進(jìn)去就可以了。
??有一點(diǎn)抚太,這里使用構(gòu)造方法傳參數(shù)并不是必須的塘幅,當(dāng)然我們可以通過其他方式傳遞參數(shù),只需要把參數(shù)傳遞過去即可尿贫。
其實(shí)從上面代碼中我們可以分析得到:
- 策略模式就是對(duì)于同一行為(出行)电媳,通過不同的實(shí)現(xiàn)(汽車,火車庆亡,自行車)匾乓,達(dá)到相同的目的。
- 策略模式的側(cè)重點(diǎn)就是在行為上又谋,所以要對(duì)行為進(jìn)行抽象拼缝,所以很適合用接口來表示。
- 很多時(shí)候彰亥,策略的實(shí)現(xiàn)可以通過匿名內(nèi)部類或者Lambda表達(dá)式的形式來實(shí)現(xiàn)咧七,比如Collections的sort方法;
??既然說道了Collections的sort方法任斋,我們?cè)僖訡ollections的sort方法來舉一個(gè)例子继阻,比如我們要對(duì)自定義對(duì)象進(jìn)行排序:
自定義對(duì)象Person,我們要根據(jù)其中的屬性進(jìn)行排序:
public class Person {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
自定義比較器PersonComparator:
public class PersonComparator implements Comparator<Person>{
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
}
進(jìn)行測(cè)試:
public class ComparatorTest {
public static void main(String[] args) {
List<Person> list = getPersonList();
Collections.sort(list, new PersonComparator());
System.out.println(list);
}
public static List<Person> getPersonList() {
Person person1 = new Person();
person1.setAge(10);
Person person2 = new Person();
person2.setAge(15);
Person person3 = new Person();
person3.setAge(12);
List<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.add(person3);
return list;
}
}
打印結(jié)果:
[Person{age=10}, Person{age=12}, Person{age=15}]
當(dāng)然废酷,這種情況我們也可以使用匿名類來實(shí)現(xiàn)該功能:
public static void main(String[] args) {
List<Person> list = getPersonList();
Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
});
System.out.println(list);
}
然后我們也可以使用Lambda表達(dá)式來實(shí)現(xiàn):
Collections.sort(list, (o1, o2) -> o1.getAge() - o2.getAge());
再然后瘟檩,我們還可以使用JDK8中中Comparator里的comparingInt來實(shí)現(xiàn):
Collections.sort(list, Comparator.comparingInt(Person::getAge));
從上面就可以看出來,Collections.sort方法就是策略模式的一種很好的詮釋澈蟆。這里的Comparator就相當(dāng)于Strategy角色墨辛,而Collections則具備了Context的角色。
總結(jié)
- 策略模式趴俘,就是對(duì)于同一行為睹簇,通過不同的實(shí)現(xiàn),完成相同的功能哮幢。策略模式封裝的是一種變化的狀態(tài)带膀。所以說當(dāng)我們有類似的,需要針對(duì)不同的情況實(shí)現(xiàn)不同的規(guī)則的時(shí)候橙垢,不妨考慮使用下策略模式垛叨。
- 很多時(shí)候策略類可以使用匿名類或JDK8之后的Lambda表達(dá)式來實(shí)現(xiàn),從而避免實(shí)現(xiàn)太多的類;
- 使用策略模式的時(shí)候還會(huì)有一個(gè)問題,因?yàn)椴呗阅J街兴惴ǖ倪x擇是由客戶端決定的,所以策略模式在使用的時(shí)候客戶端必須要知道所有的策略類樱衷,明白不同的策略類處理哪些不同的功能啦逆。然后根據(jù)需要決定使用哪一個(gè)策略類评疗。
本文參考自:
深入理解Arrays.sort()
策略設(shè)計(jì)模式使用
《大話設(shè)計(jì)模式》