设计模式之策略模式Strategy

目录

1. 概念

2.demo

3. 模式在开源软件中的应用

 

在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以乘坐飞机、乘坐火车、骑自行车或自己开私家车等,超市促销可以釆用打折、送商品、送积分等方法。
在软件开发中也常常遇到类似的情况,当实现某一个功能存在多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能,如数据排序策略有冒泡排序、选择排序、插入排序、二叉树排序等。
如果使用多重条件转移语句实现(即硬编码),不但使条件语句变得很复杂,而且增加、删除或更换算法要修改原代码,不易维护,违背开闭原则。如果采用策略模式就能很好解决该问题。

1. 概念

定义(Strategy):定义一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的替换不会影响使用的客户。策略模式通过对算法进行封装,把算法的实现和算法的责任分割开来,并委派给不同的对象对这些算法进行管理。

优点:

  1. 多重条件语句不易维护,而使用策略模式可以避免多重条件语句;
  2. 策略模式提供了一系列可供重用的算法族,恰当的使用继承可以把算法族的公共部分转移到父类里面,从而避免代码的重复;
  3. 策略模式可以提供相同行为的不同实现,客户可以根据不同的时间和空间要求选择不同的;
  4. 策略模式提供了对开闭原则的完美支持,可以在不修改原有代码的情况下,灵活增加新算法;
  5. 策略模式把算法的使用外放到环境类中,而算法的实现移到具体策略类中,实现了两者的分离。

缺点:

  1. 客户端必须理解所以策略算法的区别,以便适时的选择恰当的算法类;
  2. 策略模式造成过多的策略类。

使用场景

  1. 系统有很多类,而他们的区别就仅仅是行为的不同;
  2. 一个系统需要在多种算法中选择一种。

2.demo

package com.example.myalgorithm.designPattern;import java.util.HashMap;
import java.util.Map;public class A17Strategy {public interface PromotionStrategy{void doPromotion();}/*** 立减促销*/public static class LiJianPromotionStrategy implements PromotionStrategy {@Overridepublic void doPromotion() {System.out.println("促销立减,商品价格减去促销价格...");}}/*** 返现促销*/public static class FanXianPromotionStrategy implements PromotionStrategy {@Overridepublic void doPromotion() {System.out.println("返现促销,购买商品返现50元...");}}/*** 满减促销*/public static class ManJianPromotionStrategy implements PromotionStrategy {@Overridepublic void doPromotion() {System.out.println("满减促销,满200减20...");}}/*** 无促销*/public static class EmptyPromotionStrategy implements PromotionStrategy {@Overridepublic void doPromotion() {System.out.println("无促销活动");}}/*** 环境类 - 促销工厂*/public static class PromotionStrategyFactory {private static Map promotionStrategyMap = new HashMap<>();private final static EmptyPromotionStrategy EMPTY_PROMOTION_STRATEGY = new EmptyPromotionStrategy();static {promotionStrategyMap.put(promotionEnum.FAN_XIAN.type, new FanXianPromotionStrategy());promotionStrategyMap.put(promotionEnum.MAN_JIAN.type, new ManJianPromotionStrategy());promotionStrategyMap.put(promotionEnum.LI_JIAN.type, new LiJianPromotionStrategy());}private PromotionStrategyFactory() {}public static PromotionStrategy getPromotionStrategy(String promotionType) {PromotionStrategy promotionStrategy = promotionStrategyMap.get(promotionType);return promotionStrategy == null ? EMPTY_PROMOTION_STRATEGY : promotionStrategy;}private enum promotionEnum {MAN_JIAN("manjian", "满减"),FAN_XIAN("fanxian", "返现"),LI_JIAN("lijian", "立减");private String type;private String desc;promotionEnum(String type, String desc) {this.type = type;this.desc = desc;}}}public static void main(String[] args) {String promotionType = "lijian";PromotionStrategy promotionStrategy = PromotionStrategyFactory.getPromotionStrategy(promotionType);promotionStrategy.doPromotion();promotionType = "manjian";promotionStrategy = PromotionStrategyFactory.getPromotionStrategy(promotionType);promotionStrategy.doPromotion();}}

运行结果

促销立减,商品价格减去促销价格...
满减促销,满200减20...

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

 

3. 模式在开源软件中的应用

3.1 java.util.Comparator 类

public interface Comparator {int compare(T o1, T o2);
}

Comparator 就是作为一个抽象策略接口,拥有众多实现 compare 方法的具体策略,如 Arrays 类和 TreeMap 类。

public class Arrays {public static  void sort(T[] a, int fromIndex, int toIndex,Comparator c) {if (c == null) {sort(a, fromIndex, toIndex);} else {rangeCheck(a.length, fromIndex, toIndex);if (LegacyMergeSort.userRequested)legacyMergeSort(a, fromIndex, toIndex, c);elseTimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);}} 
}public class TreeMapextends AbstractMapimplements NavigableMap, Cloneable, java.io.Serializable
{/*** The comparator used to maintain order in this tree map, or* null if it uses the natural ordering of its keys.** @serial*/private final Comparator comparator;final int compare(Object k1, Object k2) {return comparator==null ? ((Comparable)k1).compareTo((K)k2): comparator.compare((K)k1, (K)k2);}  
} 

3.2 org.springframework.core.io.Resource 类
在 Spring 中提供资源访问的 Resource 接口,就是一个抽象策略类,实现该接口的众多具体策略类如:ClassPathContextResource、FileSystemContextResource等。
 

public interface Resource extends InputStreamSource {boolean exists();boolean isReadable();boolean isOpen();URL getURL() throws IOException;URI getURI() throws IOException;File getFile() throws IOException;long contentLength() throws IOException;long lastModified() throws IOException;Resource createRelative(String var1) throws IOException;String getFilename();String getDescription();
}

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部