1、为什么我们要使用设计模式;
使用设计模式可以重构整体架构代码,提高代码复用性、扩展性。
2、设计模式六大原则;
开闭原则:
开闭原则就是对扩展开放,对修改关闭,在程序需要扩展的时候,不能去修改原有的代码,实现一个热插拔的效果。
里氏替换原则:
里氏替换原则是面向对象设计的基本原则之一,里氏替换原则中说,任何基类可以出现的地方,子类一定可以出现。里氏替换原则是对开闭原则的补充,实现开闭原则的关键步骤就是抽象化。
依赖倒转原则:
这是开闭原则的基础,直接对接口编程,以来抽象不依赖于具 体。
接口隔离原则:
使用多个隔离的接口比使用单个接口要好
迪米特法则(最少知道原则):
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统 功能模块相对独立。
合成复用原则:
原则是尽量使用合成/聚合的方式,而不是使用继承。
2、策略者模式
策略者模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决多重If判断的问题。
3、使用策略者模式有以下几个角色
环境角色(Context):持有一个Strategy引用;
抽象策略角色(Strategy):这是一个抽象角色,通常由一个接口或抽象类实现,此角色给出所有具体类略类所需的接口;
具体策略角色(ConcreteStrategy):包装了相关的算法或行为.
4、策略者模式的使用场景
比如:搭建聚合支付平台,这个时候需要调用很多第三方支付接口,支付宝、微信、银联、小米等等支付接口。
如果通过以下这种if判断来实现,如果以后想要增加一种支付方式,后期的维护性就会非常差。
public String toPayHtml2(String payCode){if(payCode.equals("ali_pay")){return "调用支付宝接口...";}if(payCode.equals("xiaomi_pay")){return "调用小米支付接口";}if(payCode.equals("yinlian_pay")){return "调用银联支付接口...";}return "未找到该接口...";}
策略者模式架构图
以下就架构图上的每一角色写代码
抽象角色:
public interface PayStrategy {/*** 共同算法实现骨架* @return*/public String toPayHtml();}
具体实现角色:
@Componentpublic class AliPayStrategy implements PayStrategy {public String toPayHtml() {return "调用支付宝支付接口";}}@Componentpublic class XiaoMiPayStrategy implements PayStrategy {public String toPayHtml() {return "调用小米支付接口";}
环境角色:
@RestControllerpublic class PayContextService {@Autowiredprivate PaymentChannelMapper paymentChannelMapper;@Autowiredprivate SpringUtils springUtils;@RequestMapping("/toPayHtml")public String toPayHtml(String payCode){// 1.验证参数if(StringUtils.isEmpty(payCode)){return "payCode不能为空!";}// 2.使用PayCode查询PaymentChannelEntity paymentChannel = paymentChannelMapper.getPaymentChannel(payCode);if(paymentChannel==null){return "该渠道为空...";}// 3.获取策略执行的beanidString strategyBeanId = paymentChannel.getStrategyBeanId();// 4.使用strategyBeanId获取对应spring容器bean信息PayStrategy payStrategy = springUtils.getBean(strategyBeanId, PayStrategy.class);// 5.执行具体策略算法return payStrategy.toPayHtml();}}
这个里边有用到了一个工具SpringUtils
@Componentpublic class SpringUtils implements ApplicationContextAware {private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}//获取applicationContextpublic static ApplicationContext getApplicationContext() {return applicationContext;}//通过name获取 Bean.public static Object getBean(String name){return getApplicationContext().getBean(name);}//通过class获取Bean.public static <T> T getBean(Class<T> clazz){return getApplicationContext().getBean(clazz);}//通过name,以及Clazz返回指定的Beanpublic static <T> T getBean(String name,Class<T> clazz){return getApplicationContext().getBean(name, clazz);}}
其实这个工具也可以替换为我们自己些一个本地缓存Map(id,实体)
还有就是为什么要查询数据库:是因为要动态维护前端传来type与我们具体策略类的映射关系。
