策略模式
参考:
三种新姿势:帮你干掉过多的if-else (qq.com)
http://t.csdn.cn/5YeOZ
http://t.csdn.cn/HcGYw
JAVASE中GUI编程中,布局管理 ;
Spring框架中,Resource接口,资源访问;
javax.servlet.http.HttpServlet#service();
如果一个方法有大量if else语句,可通过策略模式来消除掉;
一个系统,需要动态地在几个算法中选择一种,可用策略模式实现;
系统有很多类,而他们的区别仅仅在于他们的行为不同
优点:
- 开闭原则;
- 避免使用多重条件转移语句;
- 提高了算法的保密性和安全性:可使用策略模式以避免暴露复杂的,与算法相关的数据结构。
三种角色
- 环境 (Context):持有一个策略类的引用,最终给客户端调用。
- 抽象策略 (Strategy): 策略类,通常是一个接口或者抽象类。
- 具体策略 (ConcreteStrategy):实现了策略类中的策略方法,封装相关的算法和行为。
在使用时,直接使用(环境)的类,通过不同状态类型,给他装配不同的实现的具体策略,以此来实现灵活装配
两个原则:
- 封装变化的概念。
- 编程中使用接口,而不是使用的是具体的实现类(面向接口编程)。
理解:
对一系列相似类型的算法逻辑进行接口封装,有调用者决定具体使用哪一套实现的逻辑算法;
针对接口编程,而不是针对实现编程,使用哪个接口的实现类就是具备这个实现类的特性
简单例子:
TreeSet进行比较时,需要指定Comparator接口类型,用户根据自己的规则升序还是降序,自定义实现接口来灵活控制
package com.ung.myBatisPlusTest.mode.policyMode;
/**
* @author: wenyi
* @create: 2022/8/30
* @Description:
*/
public class TestStrategy {
public static void main(String[] args) {
String type = "普通客户小批量";
double price = 100;
//使用if else
// price = getPrice(type, price);
//使用策略模式
// Context context = new Context();
// context.setStrategy(new OldCustomerManyStrategy());
// price = context.getPrice(price);
//使用策略模式
Context context = new Context();
Strategy strategy = StrategyFactory.getInstance().getStrategy(type);
context.setStrategy(strategy);
price = context.getPrice(price);
System.out.println(price);
}
/**
* if else
* 实现简单
* 缺点明显,类型较多需要修改时,难以维护
*/
public static double getPrice(String type, double price) {
if (type.equals("普通客户小批量")) {
System.out.println("不打折,原价");
return price;
} else if (type.equals("普通客户大批量")) {
System.out.println("打九折");
return price * 0.9;
} else if (type.equals("老客户小批量")) {
System.out.println("打八五折");
return price * 0.85;
} else if (type.equals("老客户大批量")) {
System.out.println("打八折");
return price * 0.8;
}
return price;
}
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author: wenyi
* @create: 2022/8/30
* @Description: 环境 用来装配使用策略接口
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Context {
private Strategy strategy;
public double getPrice(double price) {
return strategy.getPrice(price);
}
}
/**
* @author: wenyi
* @create: 2022/8/30
* @Description: 策略类,通过不同实现类实现不同策略
*/
public interface Strategy {
double getPrice(double price);
}
/**
* @author: wenyi
* @create: 2022/8/30
* @Description:
*/
public class NewCustomerFewStrategy implements Strategy {
@Override
public double getPrice(double price) {
System.out.println("不打折,原价");
return price;
}
}
/**
* @author: wenyi
* @create: 2022/8/30
* @Description:
*/
public class NewCustomerManyStrategy implements Strategy {
@Override
public double getPrice( double price) {
System.out.println("打九折");
return price*0.9;
}
}
package com.ung.myBatisPlusTest.mode.policyMode;
/**
* @author: wenyi
* @create: 2022/8/30
* @Description:
*/
public class OldCustomerFewStrategy implements Strategy {
@Override
public double getPrice( double price) {
System.out.println("打八五折");
return price*0.85;
}
}
package com.ung.myBatisPlusTest.mode.policyMode;
/**
* @author: wenyi
* @create: 2022/8/30
* @Description:
*/
public class OldCustomerManyStrategy implements Strategy {
@Override
public double getPrice( double price) {
System.out.println("打八折");
return price*0.8;
}
}
使用工厂+单例模式将选择权交给使用者
package com.ung.myBatisPlusTest.mode.policyMode;
import com.google.common.collect.ImmutableMap;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.security.PublicKey;
import java.util.Map;
/**
* @author: wenyi
* @create: 2022/8/30
* @Description: 单例 工厂模式
*/
@Data
@NoArgsConstructor
public class StrategyFactory {
private static Map<String, Strategy> map;
/**
* 维护一个map作为工厂模式
*/
static {
map = ImmutableMap.of(
"普通客户小批量", new NewCustomerFewStrategy(),
"普通客户大批量", new NewCustomerManyStrategy(),
"老客户小批量", new OldCustomerFewStrategy(),
"老客户大批量", new OldCustomerManyStrategy()
);
}
public static class SingletonHolder {
public static StrategyFactory strategyFactory = new StrategyFactory();
}
public static StrategyFactory getInstance() {
return SingletonHolder.strategyFactory;
}
public Strategy getStrategy(String type) {
return map.get(type);
}
}
总结:
个人理解就是一个 操作类 Context ,里面有属性策略 Strategy接口
Strategy接口有不同的策略实现类,通过给Context 构造不同的Strategy实现类,来实现不同的策略使用。