首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >设计模式12之策略模式

设计模式12之策略模式

作者头像
Lvshen
发布2022-05-05 17:46:22
发布2022-05-05 17:46:22
3930
举报

背景

策略模式是一种比较简单的设计模式,生活中做成一件事有几种不同的策略选择供你达成。比如你上班可以选择坐公交上班,可以选择坐地铁上班,也可以选择自驾上班,甚至还可以步行上班。

如果需要用代码表示上面的内容,你可以使用多重条件语句实现。

代码语言:javascript
复制
if("1".equals(status)) {
   return "公交";
} else if("2".equals(status)) {
   return "地铁";
} else if("3".equals(status)) {
   return "自驾";
} else if("4".equals(status)) {
   return "步行";
} 

但是上面这样的代码实际就是硬编码,如果需要增加、移除、修改算法,需要在这里修改,违反了开闭原则。这个问题可以使用策略模式解决。

如果使用if语句,大概是这样的一个流程图:

if语句

使用策略模式的流程图:

策略模式

什么是策略模式

“Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。) ”

将算法调用方与算法实现方分割开来,实现两者之间的解耦。

策略模式的主要组成要素如下:

  • 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
  • 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

代码实现

How2WorkStrategy

抽象策略类

代码语言:javascript
复制
interface How2WorkStrategy {
    String how2WorkFun();
}

SubwayStrategy

地铁策略类

代码语言:javascript
复制
public class SubwayStrategy implements How2WorkStrategy{
    @Override
    public String how2WorkFun() {
        return "地铁";
    }
}

CarStrategy

自驾小车策略类

代码语言:javascript
复制
public class CarStrategy implements How2WorkStrategy{
    @Override
    public String how2WorkFun() {
        return "自驾";
    }
}

BusStrategy

公交车策略类

代码语言:javascript
复制
public class BusStrategy implements How2WorkStrategy{
    @Override
    public String how2WorkFun() {
        return "公交";
    }
}

WalkStrategy

步行策略类

代码语言:javascript
复制
public class WalkStrategy implements How2WorkStrategy{
    @Override
    public String how2WorkFun() {
        return "步行";
    }
}

Context

装载类,可理解为策略工厂。

代码语言:javascript
复制
public class Context {
    public How2WorkStrategy getHow2WorkStrategy() {
        return how2WorkStrategy;
    }

    public void setHow2WorkStrategy(How2WorkStrategy how2WorkStrategy) {
        this.how2WorkStrategy = how2WorkStrategy;
    }

    private How2WorkStrategy how2WorkStrategy;

    public String how2Work() {
        return how2WorkStrategy.how2WorkFun();
    }

}

测试代码:

代码语言:javascript
复制
@org.junit.Test
public void test() {
    Context context = new Context();
    How2WorkStrategy how2WorkStrategy = new CarStrategy();
    context.setHow2WorkStrategy(how2WorkStrategy);
    String s = context.how2Work();
    Console.log(s);
    Console.log("---------------------");
    how2WorkStrategy = new BusStrategy();
    context.setHow2WorkStrategy(how2WorkStrategy);
    String s1 = context.how2Work();
    Console.log(s1);
}

我们选择自驾策略和公交车策略,测试结果如下:

代码语言:javascript
复制
自驾
---------------------
公交

上面代码还有缺限,上层模块必须知道有哪些策略,然后才能决定使用哪一个策略,这与迪米特法则是相违背的,我只是想使用了一个策略,我凭什么就要了解这个策略呢?那要你的封装类还有什么意义?这是原装策略模式的一个缺点,幸运的是,我们可以使用其他模式来修正这个缺陷,如工厂方法模式、代理模式或享元模式。

关于策略模式的思考

策略模式比较简单,如果存在多重if语句。并且if语句还有可能变化,那么我们就可以将if语句中的算法封装到类中,使用策略模式代替if语句。

总之策略模式就是:算法可自由切换、避免多重if-else语句、更好的扩展性。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-26,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 背景
  • 什么是策略模式
  • 代码实现
    • How2WorkStrategy
    • SubwayStrategy
    • CarStrategy
    • BusStrategy
    • WalkStrategy
    • Context
  • 关于策略模式的思考
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档