设计模式-策略模式(一)

序言

  都毕业好几年了,对于设计模式,平时也偶尔接触过,但却没有系统的学习过,自然在遇到问题找解决方案的时候,也很少能想到设计模式,感觉总是一种模糊的状态,所以,准备重写梳理一下。

注:本系列设计模式相关代码,开发语言使用Java,JDK版本基于1.8。

概述

  策略模式是属于一种行为型的设计模式,针对的是算法。我们可以通俗的理解为,策略模式就是对某一行为,能根据不同的实现,完成相同的功能。比如排序,我们能根据不同的类型,调用不同的实现,来实现相同的功能,就是排序。

实现

策略模式中涉及到三个角色:

  1. Context角色:持有一个Strategy角色的引用;
  2. Strategy(抽象策略)角色:该角色通常是接口或抽象类;
  3. ConcreteStrategy(具体策略)角色:实现了抽象策略角色的算法。
策略模式.png

实例

  我们拿一个例子来加深对策略模式的了解。比如大家出去旅游,可以选择开火车,也可以选择骑自行车,也可以选择做汽车。这其实就是一种策略模式的应用。

Strategy角色
public interface Strategy {
    void travel();
}

抽象角色,只有一个方法,就是出行的方法。

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角色

出去玩的对象是人:

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();
    }
}

打印结果:

--骑自行车出去玩--
--坐火车出去玩--

  这时候如果说,这时候出行的方式要改为坐轮船,其实这就相当于更改策略,那我们再实现一个类,然后再调用的时候想办法把参数传进去就可以了。
  有一点,这里使用构造方法传参数并不是必须的,当然我们可以通过其他方式传递参数,只需要把参数传递过去即可。

其实从上面代码中我们可以分析得到:

  1. 策略模式就是对于同一行为(出行),通过不同的实现(汽车,火车,自行车),达到相同的目的。
  2. 策略模式的侧重点就是在行为上,所以要对行为进行抽象,所以很适合用接口来表示。
  3. 很多时候,策略的实现可以通过匿名内部类或者Lambda表达式的形式来实现,比如Collections的sort方法;

  既然说道了Collections的sort方法,我们再以Collections的sort方法来举一个例子,比如我们要对自定义对象进行排序:
自定义对象Person,我们要根据其中的属性进行排序:

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();
    }
}

进行测试:

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;
    }
}

打印结果:

[Person{age=10}, Person{age=12}, Person{age=15}]

当然,这种情况我们也可以使用匿名类来实现该功能:

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表达式来实现:

Collections.sort(list, (o1, o2) -> o1.getAge() - o2.getAge());

再然后,我们还可以使用JDK8中中Comparator里的comparingInt来实现:

Collections.sort(list, Comparator.comparingInt(Person::getAge));

从上面就可以看出来,Collections.sort方法就是策略模式的一种很好的诠释。这里的Comparator就相当于Strategy角色,而Collections则具备了Context的角色。

总结

  1. 策略模式,就是对于同一行为,通过不同的实现,完成相同的功能。策略模式封装的是一种变化的状态。所以说当我们有类似的,需要针对不同的情况实现不同的规则的时候,不妨考虑使用下策略模式。
  2. 很多时候策略类可以使用匿名类或JDK8之后的Lambda表达式来实现,从而避免实现太多的类;
  3. 使用策略模式的时候还会有一个问题,因为策略模式中算法的选择是由客户端决定的,所以策略模式在使用的时候客户端必须要知道所有的策略类,明白不同的策略类处理哪些不同的功能。然后根据需要决定使用哪一个策略类。

本文参考自:
深入理解Arrays.sort()
策略设计模式使用
《大话设计模式》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,784评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,745评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,702评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,229评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,245评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,376评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,798评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,471评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,655评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,485评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,535评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,235评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,793评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,863评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,096评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,654评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,233评论 2 341

推荐阅读更多精彩内容

  • 一直想把常见的设计模式系统地学习一遍,结果和大多数人一样,过了几天就没能坚持下去了。我发现学习这件事情急不得,往往...
    Neulana阅读 559评论 5 2
  • 前言 设计模式是我们实际应用开发中必不可缺的,对设计模式的理解有助于我们写出可读性和扩展更高的应用程序。虽然设计模...
    丶legend阅读 528评论 0 3
  • 思考: 假设有个需求,模拟鸭子游戏:在游戏中会出现各种各样的鸭子,一边游泳戏水,一边呱呱叫。开始我们的设计吧: 这...
    MarksGui阅读 177评论 0 0
  • “夏明秀死了,前几天在医院死了。”姐姐回家后一脸倦容的说道。 其实论起辈分来,我是夏老太的干孙女,...
    宫长青筝阅读 146评论 0 0
  • 程专栏连载的练手项目篇,如有兴趣可以访问前三篇: 有哪些适合新手练手的Java项目? - 学习编程 - 知乎专栏 ...
    达魔学院阅读 437评论 0 2