策略模式在生活中体现不少。java
咱们要去旅游,咱们能够选择不一样的出行方式:飞机,火车,大巴,自驾等,这是不一样的策略。算法
双十一当当网购买满减活动,满 100 减 50,满 200 减 100,满 400 减 250 等,这也是不一样的策略。设计模式
抑或是咱们在追求女生时,针对不一样性格的女孩子采用不一样的方式,这仍是不一样的策略。安全
策略模式在程序中的体现依然淋漓尽致。框架
好比咱们的图片加载,Android 上有 Fresco
,Picasso
,Glide
,Universal-Image-Loader
等,iOS 上有 SDWebImage
、AFNetworking
、FastImageCache
等。ide
因此,假设让你来设计一个图片加载上层框架,要求能够底层可使用 A B 两种加载策略,你会怎么作呢?学习
// 加载类A public class ImageLoadServiceA { public void loadImage() { System.out.println("使用 A 加载框架"); } } // 加载类B public class ImageLoadServiceB { public void loadImage() { System.out.println("使用 B 加载框架"); } } // 使用 public void loadNetImage(boolean useA) { if(useA){ new ImageLoadServiceA().loadImage();// 使用A加载方式 } else { new ImageLoadServiceB().loadImage();// 使用B加载方式 } }
能够看到,上述经过一个 useA
参数判断是否使用 A 框架,为 true
使用 A,不然使用 B 框架进行加载。动画
但假设咱们如今须要再支持一个 C 框架的使用,你可能想到了,那就再加一个 boolean 参数 useB
便可,或者直接使用一个 int 参数 loadType
,宏定义 0 表明 A 框架,1 表明 B 框架,2 表明 C 框架,这样若是须要增长方式则更新取值便可。this
设计模式不过是咱们写程序的招式,因为以前你们可能还学习过了简单工厂模式,咱们不妨在这里进行实战。设计
// 抽象图片加载类 public abstract class ImageLoadService { public abstract void loadImage(); } // 具体加载类A public class ImageLoadServiceA extends ImageLoadService { @Override public void loadImage() { System.out.println("使用 A 加载框架"); } } //具体加载类B public class ImageLoadServiceB extends ImageLoadService { @Override public void loadImage() { System.out.println("使用 B 加载框架"); } } //具体加载类C public class ImageLoadServiceC extends ImageLoadService { @Override public void loadImage() { System.out.println("使用 C 加载框架"); } } public class ImageLoadFactory { public static ImageLoadService create(int loadType) { ImageLoadService loadService = null; switch (loadType) { case 0: loadService = new ImageLoadServiceA(); break; case 1: loadService = new ImageLoadServiceB(); break; case 2: loadService = new ImageLoadServiceC(); break; } return loadService; } } // 使用 public void loadNetImage(int loadType) { ImageLoadFactory.create(loadType).loadImage(); }
能够看到,咱们使用简单工厂模式后,在处理新增其余加载方式的问题的时候,不会再去影响原有的加载类代码,若是新增一种加载方式的话,咱们只须要新增 ImageLoadXXX
类,实现 loadImage()
加载方法,再修改工厂类 ImageLoadFactory
便可。
相信你也发现了,这个方式只能解决对象的建立问题,咱们每次新增方式的时候都会新增一个类,并且须要对工厂类进行代码修改,显然是违反了开闭原则。
人生到处有策略,上面的不一样的加载方式其实就是不一样的「策略」。
策略模式是对 算法的封装,它将每个算法封装到具备共同接口的独立的类中,从而使得它们能够独立变换。
要学习一个设计模式,先要学会临摹,因此上面的需求,咱们能够实现为:
public interface ImageLoadStrategy { void loadImage() ; }
// 具体加载类A public class ImageLoadStrategyA implements ImageLoadStrategy { @Override public void loadImage() { System.out.println("使用 A 加载框架"); } } //具体加载类B public class ImageLoadStrategyB implements ImageLoadStrategy { @Override public void loadImage() { System.out.println("使用 B 加载框架"); } } //具体加载类C public class ImageLoadStrategyC implements ImageLoadStrategy { @Override public void loadImage() { System.out.println("使用 C 加载框架"); } }
public class ContextImageLoadStrategy { private ImageLoadStrategy strategy ; public ContextImageLoadStrategy(ImageLoadStrategy strategy){ this.strategy = strategy ; } public void loadImage(){ strategy.loadImage(); } }
public void loadImage(ImageLoadStrategy imageLoadStrategy){ ContextImageLoadStrategy contextStrategy = new ContextImageLoadStrategy(imageLoadStrategy); contextStrategy.loadImage(); }
注意: 策略的核心不是如何实现算法,而是如何更优雅的把这些算法组织起来,让客户端很是好调用「虽然策略很是多,能够自由切换,可是同一时间客户端只能调用一个策略,其实也很好理解,你不可能同时既坐飞机,又坐火车」。
if-else
或者 switch
)。你有想到如何解决「客户端必须知道全部的策略类」这个缺点么?
if-else
或者 switch
语句来选择具体行为时。使用策略模式把这些行为独立到具体的策略类中,能够避免多重选择的结构。想必你们已经很清楚上面的策略模式了,下面源码中用到策略模式了吗?
ListView
的 ArrayAdapter
、SimpleAdapter
;总的来讲,策略模式还算咱们项目开发中会使用很是频繁的模式,你学会了么?若有疑问,请在评论区留言。