策略模式
策略模式
使用策略模式,可以使一个类的行为在运行时得到改变。为了使用策略模式,首先我们需要创建一些列的算法,将他们进行封装,并且使他们可以相互替换(具体为所有的策略算法都实现自同一个interface)。使用策略模式可以使得代码中减少很多的 if... else
结构。下面通过一个场景对比 if... else
和策略模式。
出去旅游的时候,我们经常根据天气决定我们的行为。例如:下雨的时候我们则会选择室内,例如博物馆;晴天的时候我们则会选择公园等景色比较好的地方;当遇到极端天气的时候我们一般宅在家里不出门。
针对以上场景,我们很容易写出一下 if... else
的代码:
public void doAction(String weather) { if("rainy".equals(weather)) { System.out.println("下雨了,我们去博物馆吧"); } if ("sunny".equals(weather)) { System.out.println("晴天了,我们去公园吧"); } if ("very-bad".equals(weather)) { System.out.println("极端天气,我们宅在家吧"); } }
乍一看这样的代码没有问题,确实这样的代码毫无问题,当时随着越来越多的条件,就会有越来越多的 if... else
,使得代码变得冗长。那如何使得精简这样的代码呢?答案就是本文的主人公:策略模式。
策略模式要求我们提前定义好一些列的策略算法:
// 定义接口 public interface IAction { void doAction(); } // 下雨天策略类 public class RainyAction implements IAction { @Override public void doAction() { System.out.println("下雨了,我们去博物馆吧"); } } // 晴天策略类 public class SunnyAction implements IAction { @Override public void doAction() { System.out.println("晴天了,我们去公园吧"); } } // 极端天气策略类 public class VeryBadAction implements IAction { @Override public void doAction() { System.out.println("极端天气,我们宅在家吧"); } }
在使用时,我们根据不同的天气,选择不同的策略类即可:
public class Client { public static void main(String[] args) { Map<String, IAction> map = new HashMap<>(); map.put("rainy", new RainyAction()); map.put("sunny", new SunnyAction()); map.put("very-bad", new VeryBadAction()); map.get("rainy").doAction(); // 输出:下雨了,我们去博物馆吧 map.get("sunny").doAction(); // 输出:晴天了,我们去公园吧 map.get("very-bad").doAction(); // 输出:极端天气,我们宅在家吧 } }
通过上面代码发现,我们将之前的每一个 if... else
分支,变成了一个策略类。根据不同的场景,选择对应的策略类,执行对应的策略方法。经过对比我们可以现在策略模式的一些优缺点:
优点:
- 代码比
if... else
更加优雅。当if越多时,提现的越明显 - 扩展性好。当添加新的策略时,只需新编写一个策略类即可,符合“开闭原则”
缺点:
- 策略类会非常多。之前的
if... else
只集中在一个类里,现在需要扩展多个类。