最近入职公司一个月了,啥事没干居家培训了大半个月,今天第一天入场没啥事干逛了一天倔金,看到了一个策略模式感觉不错就学了一下。
拒绝if、else!!!代码可以更加优雅~
用我自己的语言去描述下这个策略模式:首先新建一个接口,接口中定义一个方法;然后将每个if中的代码逻辑抽取到一个重写了接口方法的新建类中(每一个if的代码模块都代表你要新建一个类),然后这个时候新建一个类将定义的接口注入,然后在写一个方法(里面直接用注入的接口调用方法就行了);
如果是按照之前的写法就是一直if到底就可以,如果逻辑简单if格式看着也还行,但是如果后期需要去修改计算逻辑会很麻烦。
这边就直接使用策略模式了(有两种方案,核心都是通过多态去实现,只是取的方式不一样)
方案一:(通过实现类中的方法返回值去拿到具体应该执行的类)
public interface MemberStrategy {
// 一个标记等级的,也可以是字符串,项目中可以弄成常量
Integer vipLevel();
//price商品的价格 n商品的个数
double calcPrice(double price, int n);
}
具体的实现类:(后续如果计算逻辑修改直接在此处修改就行了)
// 普通会员——不打折
@Component
public class PrimaryMemberStrategy implements MemberStrategy { // 实现策略
//重写策略方法具体实现功能
@Override
public Integer vipLevel(){
return 1;
}
@Override
public double calcPrice(double price, int n) {
return price * n;
}
}
// 中级会员 打百分之10的折扣
@Component
public class IntermediateMemberStrategy implements MemberStrategy{
@Override
public Integer vipLevel(){
return 2;
}
@Override
public double calcPrice(double price, int n) {
double money = (price * n) - price * n * 0.1;
return money;
}
}
// 高级会员类 20%折扣
@Component
public class AdvanceMemberStrategy implements MemberStrategy{
@Override
public Integer vipLevel(){
return 3;
}
@Override
public double calcPrice(double price, int n) {
double money = price * n - price * n * 0.2;
return money;
}
}
这个是具体使用的类:
/**
* 负责和具体的策略类交互
* 这样的话,具体的算法和直接的客户端调用分离了,使得算法可以独立于客户端独立的变化。
*/
@Component
public class MemberContext {
@Autowired
private List<MemberStrategy> memberStrategys;
// 不同的会员等级自己进行不同的逻辑
public double productionCamera(Integer type, double price, int n) {
return this.getLev(type).calcPrice(price, n);
}
// 根据type的不同来获取到不同的工种子类
private MemberStrategy getLev(Integer type) {
return this. memberStrategys
.stream()
.filter(memberStrategy -> type.equals(memberStrategy.vipLevel()))
.findFirst()
.get();
}
}
测试类:
@SpringBootTest
class MyTests {
@Resource
private MemberContext memberContext;
@Test
void contextLoads() {
System.out.println(memberContext.productionCamera(1, 300, 1));
System.out.println(memberContext.productionCamera(2, 300, 1));
System.out.println(memberContext.productionCamera(3, 300, 1));
}
}
结果:
普通会员的价格:300.0
中级会员的价格:270.0
高级会员的价格:240.0
方法二:(直接通过bean的名字去拿到)
接口:
public interface MemberStrategy {
//price商品的价格 n商品的个数
double calcPrice(double price, int n);
}
实现类:
// 普通会员——不打折
@Component("primaryMemberStrategy")
public class PrimaryMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double price, int n) {
return price * n;
}
}
// 中级会员 打百分之10的折扣
@Component("intermediateMemberStrategy")
public class IntermediateMemberStrategy implements MemberStrategy{
@Override
public double calcPrice(double price, int n) {
double money = (price * n) - price * n * 0.1;
return money;
}
}
@Component("advanceMemberStrategy")
public class AdvanceMemberStrategy implements MemberStrategy{
@Override
public double calcPrice(double price, int n) {
double money = price * n - price * n * 0.2;
return money;
}
}
@Component
public class MemberContext {
@Autowired
private ApplicationContext applicationContext;
// 不同的会员等级自己进行不同的逻辑
public double productionCamera(String type, double price, int n) {
return applicationContext
.getBean(type,MemberStrategy.class).calcPrice(price, n);
}
}
测试类:
import com.example.xiaoi_demo.vo.MemberContext;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
class MyTests {
@Resource
private MemberContext memberContext;
@Test
void contextLoads() {
System.out.println(memberContext.productionCamera("intermediateMemberStrategy", 300, 1));
System.out.println(memberContext.productionCamera("advanceMemberStrategy", 300, 1));
System.out.println(memberContext.productionCamera("primaryMemberStrategy", 300, 1));
}
}
为了健壮性可以添加一些判空,注意第二种方式如果没拿到对应的bean就是报异常