设计模式之策略模式(strategy)

基础概念

-定义:按套路先解释一下什么是策略模式:一个类的行为,能够在运行时,被更改,是行为模式的一种.(直接传传递一个对象不就好了)
-场景: 排序工具类, 需要对任何对象进行排序,需要对任何对象进行比较.但有一个前提,你不能改变sort方法本身(设计原则:开闭原则)
-实现方式:按功能,设计接口, Comparator ,定义了compare方法. (PS单方法体接口,可以用lambda表达式),定义ComparatorImpl 实现compare 接口,一种策略一种比较方式.在sort方法中,传入 Comparator 对象即可.这样就可以实现不改变sort本身,来实现增加策略的方式.
-目的:思考这个问题,很简单,如果不用这种方式,你需要做到针对各种策略,按身高排序的sort1 按体重排序的sort2,破坏了原来色sort类.(目的只有一个,横向扩展,而不是垂直式的修改)

源码应用

  • Comparator(比较器)
int compare(T o1, T o2);
  • spring Resource ,Spring 会针对不同的底层资源,提供不同的 Resource 实现类
* @see WritableResource
* @see ContextResource
* @see UrlResource
* @see FileUrlResource
* @see FileSystemResource
* @see ClassPathResource
* @see ByteArrayResource
* @see InputStreamResource
public interface Resource extends InputStreamSource {
    boolean exists();
    default boolean isReadable() {
        return exists();
    }
    default boolean isOpen() {
        return false;
    }
    default boolean isFile() {
        return false;
    }
    URL getURL() throws IOException;
   
    URI getURI() throws IOException;
    File getFile() throws IOException;
   
    default ReadableByteChannel readableChannel() throws IOException {
        return Channels.newChannel(getInputStream());
    }
    long contentLength() throws IOException;
   
    long lastModified() throws IOException;
   
    Resource createRelative(String relativePath) throws IOException;
   
    @Nullable
    String getFilename();
    String getDescription();
}
  • InstantiationStrategy 负责使用 Bean 类的默认构造函数、带参构造函数或者工厂方法等来实例化 Bean,是一个策略模式的接口。InstantiationStrategy 接口源码如下。
public interface InstantiationStrategy {
    Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
            throws BeansException;
    Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
            Constructor ctor, Object... args) throws BeansException;
    Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
            @Nullable Object factoryBean, Method factoryMethod, Object... args)
            throws BeansException;
}

模式核心

  1. 对象:client(sort类) , N策略对象以及其对应的接口
  2. 组装方式, 可以直接以属性注入,也可以以方法参数传入.这种方式,就是直接以静态属性的方式注入.(可以对比一下comparable ,comparable只能固定一种实现,毕竟 是以接口实现方式,无法做到不同的实现.)
   private static Comparator YXTopComparator = new Comparator() {
        public int compare(Object var1, Object var2) {
            Curve var3 = ((Edge)var1).getCurve();
            Curve var4 = ((Edge)var2).getCurve();
            double var5;
            double var7;
            if ((var5 = var3.getYTop()) == (var7 = var4.getYTop()) && (var5 = var3.getXTop()) == (var7 = var4.getXTop())) {
                return 0;
            } else {
                return var5 < var7 ? -1 : 1;
            }
        }
    };

3.优化了哪种代码?业务场景如下(优化if,else),这种写法的问题,如果业务有变化,需要增加 e,f,g 甚至更多的类型,每次都需要去更改调用类(这种方式是特别不友好的,),因此需要抽象一个策略接口,去做实体类,横向扩展,即可

 //根据类型不同,调用不同的物流接口(比如说顺丰,申通等等)
if (type == "a") {
       
} else if (type=="b") {
      
} else  if (type=="c"){
        
}
//优化,抽象物流策略接口
public interface ShipStrategy{
//发运接口
void ship();
}

//顺丰物流发运,策略实现类
public class SFShipStrategy implement ShipStrategy {
//发运接口
  void ship(){
  //发运
  .....
  }
}

//客户端调用(调用问题解决了,如何解决对象构造的if -else? ,根据 type = a  构建  a的策略)

shipStrategy.ship();

//1.维护 type 和class的映射关系. 2.通过spring获取策略对象(原理是反射.)
Enum ShipType{
SF("SF", "com.dzq.ship.SFShipStrategy "), ADD("ST",  "com.dzq.shipSTShipStrategy");
}


//2.通过反射获取到到对象
Class.forName(clazz).newInstance()
.....
image.png

你可能感兴趣的:(设计模式之策略模式(strategy))