基础概念
-定义:按套路先解释一下什么是策略模式:一个类的行为,能够在运行时,被更改,是行为模式的一种.(直接传传递一个对象不就好了)
-场景: 排序工具类, 需要对任何对象进行排序,需要对任何对象进行比较.但有一个前提,你不能改变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;
}
模式核心
- 对象:client(sort类) , N策略对象以及其对应的接口
- 组装方式, 可以直接以属性注入,也可以以方法参数传入.这种方式,就是直接以静态属性的方式注入.(可以对比一下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()
.....