springboot项目中使用设计模式一策略模式
策略模式:
使用常用,支付,之前做了微信支付,支付宝支付,然后另外一个同事写了一个银联支付,那么如果代码方法一起就会导致代码不是很好操作所以,采用策略模式进行,同事只需要写一个实现类,就可以了,
在协作过程中比较容易。
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。
应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
使用案例代码:
策略接口:执行的方法
package com.cxy.ssp.strategy; public interface Strategy { String getVpcList(DemoPojo demoPojo); }
实体类:
package com.cxy.ssp.strategy; public class DemoPojo { private String poolid; private String orderId; private String name; public String getPoolid() { return poolid; } public void setPoolid(String poolid) { this.poolid = poolid; } public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public DemoPojo(String poolid, String orderId, String name) { this.poolid = poolid; this.orderId = orderId; this.name = name; } public DemoPojo() { } }
实现类:
1
package com.cxy.ssp.strategy.impl; import com.cxy.ssp.strategy.DemoPojo; import com.cxy.ssp.strategy.Strategy; import org.springframework.stereotype.Component; @Component("A") public class SA implements Strategy { @Override public String getVpcList(DemoPojo demoPojo) { System.out.println("A,getVpcList ==========="+demoPojo); return demoPojo.getName(); } }
2
package com.cxy.ssp.strategy.impl; import com.cxy.ssp.strategy.DemoPojo; import com.cxy.ssp.strategy.Strategy; import org.springframework.stereotype.Component; @Component("B") public class SB implements Strategy { @Override public String getVpcList(DemoPojo demoPojo) { System.out.println("b,getVpcList ==========="+demoPojo); return demoPojo.getName(); } }
3
package com.cxy.ssp.strategy.impl; import com.cxy.ssp.strategy.DemoPojo; import com.cxy.ssp.strategy.Strategy; import org.springframework.stereotype.Component; @Component("C") public class SC implements Strategy { @Override public String getVpcList(DemoPojo demoPojo) { System.out.println("c"+demoPojo); return demoPojo.getName(); } }
策略context
package com.cxy.ssp.strategy; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /***、 *通过Spring将实现Strategy的实现类都自动注入到strategyMap类中, * 当用户传入选择的资源池时,自动根据资源池id去对应的资源池实现中查找资源。 * */ @Service public class SimpleContext { @Autowired private final Map<String, Strategy> strategyMap = new ConcurrentHashMap<>(); public SimpleContext(Map<String, Strategy> strategyMap) { this.strategyMap.clear(); strategyMap.forEach((k, v)-> this.strategyMap.put(k, v)); } public String getResource(DemoPojo demoPojo){ return strategyMap.get(demoPojo.getPoolid()).getVpcList(demoPojo); } }
策略服务L:
package com.cxy.ssp.controller; import com.cxy.ssp.strategy.DemoPojo; import com.cxy.ssp.strategy.SimpleContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController public class TestController { @Autowired private SimpleContext simpleContext; @PostMapping("/choose") public String choose(@RequestBody DemoPojo demoPojo){ return simpleContext.getResource(demoPojo); } }
外加一个核心启动类:
package com.cxy.ssp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SspApplication { public static void main(String[] args) { SpringApplication.run(SspApplication.class, args); } }
就已经完成了。思想:将实现类交给spring去管理,通过接口的注入,获取对应的类型,再通过context进行调用执行的方法:
测试:
此时应该有人怀疑:调用了同一个方法,然后输出的都是一个方法。
那么进行修改代码:
package com.cxy.ssp.strategy.impl; import com.cxy.ssp.strategy.DemoPojo; import com.cxy.ssp.strategy.Strategy; import org.springframework.stereotype.Component; @Component("A") public class SA implements Strategy { @Override public String getVpcList(DemoPojo demoPojo) { System.out.println("A,getVpcList ==========="+demoPojo); return demoPojo.getName()+"a"; } }
package com.cxy.ssp.strategy.impl; import com.cxy.ssp.strategy.DemoPojo; import com.cxy.ssp.strategy.Strategy; import org.springframework.stereotype.Component; @Component("B") public class SB implements Strategy { @Override public String getVpcList(DemoPojo demoPojo) { System.out.println("b,getVpcList ==========="+demoPojo); return demoPojo.getName()+"b"; } }
package com.cxy.ssp.strategy.impl; import com.cxy.ssp.strategy.DemoPojo; import com.cxy.ssp.strategy.Strategy; import org.springframework.stereotype.Component; @Component("C") public class SC implements Strategy { @Override public String getVpcList(DemoPojo demoPojo) { System.out.println("c"+demoPojo); return demoPojo.getName()+"c"; } }
就测试到这里,那么如果传输的那个poolid传输错误了改怎么处理呢:
服务器端报错误:说明没有这个方法,
那么可以在context中进行限制:
首先判断是否包含,如果不包含,就可以直接threw一个异常,让前台直接显示