策略模式与模版模式的区别与应用

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 策略模式与模版模式的区别与应用

本文为博主原创,未经允许不得转载:

  最近在做项目的优化,由于项目在早期缺乏规划,在开发过程中,对于某一个业务的不同类型判断,增加了很多 if else ,代码的健壮性变得很差。

所以考虑使用设计模式中的策略模式与模版模式进行开发中的代码设计。且由于在使用过程中策略模式与模版模式经常一起使用,所以对这两种设计模式

进行一起整理记录下。

 

  1.模版模式:

    模版模式的定义:模板方法模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式。让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤。

    模版模式属于行为型设计模式,其意图是在一个方法里实现一个算法,并定义延迟算法的某些步骤,从而让其他类重新定义他们。

    项目中经常使用的RestTemplate,JdbcTemplate,RedisTemplate等都采用了模版模式的设计模式,因为在操作资源的时候,经常会涉及到打开资源链接

  关闭资源连接等,且为公用的模式,所以采用模版模式,然后将其定义为一个算法骨架,通过子类或实现类来实现算法的具体实现。

    example:

    定义一个模版:

public abstract class AbstractDataSourceTemplate {
    /**
     * 开启连接
     */
    abstract void open();
    /**
     * 执行操作
     */
    abstract void execute();
    /**
     * 关闭连接
     */
    abstract void close();
    /**
     * 模版方法
     */
    public final void run() {
        open();
        execute();
        close();
    }
}

    通过上述模版实现JdbcTemplate  与 RedisTemplate

public class RedisDataSourceTemplate extends AbstractDataSourceTemplate {
    /**
     * 开启连接
     */
    @Override
    void open() {
        System.out.println("开启redis连接...");
    }
    /**
     * 执行操作
     */
    @Override
    void execute() {
        System.out.println("操作redis...");
    }
    /**
     * 关闭连接
     */
    @Override
    void close() {
        System.out.println("关闭redis连接...");
    }
}

JdbcTemplate  ::

public class JdbcDataSourceTemplate extends AbstractDataSourceTemplate {
    /**
     * 开启连接
     */
    @Override
    void open() {
        System.out.println("开启jdbc连接...");
    }
    /**
     * 执行操作
     */
    @Override
    void execute() {
        System.out.println("操作jdbc...");
    }
    /**
     * 关闭连接
     */
    @Override
    void close() {
        System.out.println("关闭jdbc连接...");
    }
}

使用

//jdbc模版
        AbstractDataSourceTemplate template = new JdbcDataSourceTemplate();
        template.run();
        System.out.println("----------------");
        //redis模版
        AbstractDataSourceTemplate template1 = new RedisDataSourceTemplate();
        template1.run();

总结

  • 封装不可变部分,扩展可变部分
  • 提取公共代码,便于维护
  • 行为由父类控制骨架/算法,子类实现
  • 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象
  • 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度

 2.策略模式:

    策略模式的应用比模版模式的应用场景更为常见。我们在开发过程中,经常会使用 if .. else if ( )  或 switch 。。 case。。等进行同一个业务的不同场景或类型判断。

  比如进行权限校验判断时,判断当前管理员是 超级管理员:userType ==1,如果是二级管理员  userType == 2....等等。这些场景都可以使用策略模式进行开发优化,可以避免

  很长的 if else 判断。

    策略模式的定义: 

 策略模式(Strategy Pattern)属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
 策略模式使得算法可以在不影响到客户端的情况下发生变化。
 其主要目的是通过定义相似的算法,替换if
else 语句写法,并且可以随时相互替换。

    在其他博客中找到一个很好的场景,是支付场景,通过策略模式区分支付宝,银行卡,点券支付的场景。


package strategy;


public interface PayStrategy {

   String selectPayWay(Integer paycode);

}

 

  规定具体策略行为

package strategy;
public class PayContext {
    private PayStrategy payStrategy;
    public String selectPayWay(Integer payCode){
        payStrategy =  StrategyFactory.getInstance().create(payCode);
        return payStrategy.selectPayWay(payCode);
    }
    public PayStrategy getPayStrategy() {
        return payStrategy;
    }
    public void setPayStrategy(PayStrategy payStrategy) {
        this.payStrategy = payStrategy;
    }
}

 

支付宝付款实现类

package strategy.paystrategy;
import strategy.PayStrategy;
public class ALPayStrategy implements PayStrategy {
    @Override
    public String selectPayWay(Integer paycode) {
        //do something
        return "支付宝支付成功";
    }
}

 

银行卡支付实现类

package strategy.paystrategy;
import strategy.PayStrategy;
public class CardPayStrategy implements PayStrategy {
    @Override
    public String selectPayWay(Integer paycode) {
        //do something
        return "银行卡支付成功";
    }
}

 

微信支付实现类

package strategy.paystrategy;
import strategy.PayStrategy;
public class WeChatPayStrategy implements PayStrategy {
    @Override
    public String selectPayWay(Integer paycode) {
        //do something
        return "微信支付成功";
    }
}

 

创建策略类的工厂

package strategy;
import pay.PayWayEnum;
import strategy.paystrategy.ALPayStrategy;
import strategy.paystrategy.CardPayStrategy;
import strategy.paystrategy.PointCouponPayStrategy;
import strategy.paystrategy.WeChatPayStrategy;
import java.util.HashMap;
import java.util.Map;
public class StrategyFactory {
    private static StrategyFactory factory = new StrategyFactory();
    private StrategyFactory(){}
    private static Map strategyMap = new HashMap<>(16);
    static {
        strategyMap.put(PayWayEnum.AL_PAY.getCode(),new ALPayStrategy());
        strategyMap.put(PayWayEnum.WEICHAT_PAY.getCode(),new WeChatPayStrategy());
        strategyMap.put(PayWayEnum.CARD_PAY.getCode(),new CardPayStrategy());
        strategyMap.put(PayWayEnum.PONIT_COUPON_PAY.getCode(),new PointCouponPayStrategy());
    }
    public PayStrategy create(Integer payCode){
        return (PayStrategy) strategyMap.get(payCode);
    }
    public static StrategyFactory getInstance(){
        return factory;
    }
}

 

实现客户端

package strategy;
public class Client {
    public static void main(String[] args) {
        PayContext payContext = new PayContext();
        System.out.println(payContext.selectPayWay(100));
    }
}

 

最后在贴一个枚举类

package pay;
public enum PayWayEnum {
    /**微信支付*/
    WEICHAT_PAY("微信支付",100),
    /**支付宝支付*/
    AL_PAY("支付宝支付",101),
    /**银行卡支付*/
    CARD_PAY("银行卡支付",102),
    /**点券支付*/
    PONIT_COUPON_PAY("点券支付",103);
    private String msg;
    private Integer code;
    PayWayEnum(String msg, Integer code) {
        this.msg = msg;
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public Integer getCode() {
        return code;
    }
}

  从上面代码中,我们可以看到,我们完全消除了对状态码进行判断的那些if…else的冗余代码,取而代之是直接由客户端决定使用哪种算法,

然后交由上下文获取结果。极大的增强的了扩展性,隐藏了内部实现的细节,当然我们也可以看到,策略模式由于独立策略的实现,

也使得系统内部增加了很多策略,对客户端来必须知道这些策略类实现的是那些策略,而且需要知道具体的策略条件。

  然而在实际的生产环境中我们可能不会像示例代码这样干,在实际的生产环境中我们一般会结合spring来对我们所需的策略进行操作,

这边我可以给大家有个具体的思路,大家可以通过这个思路来想想,自己在实际生产环境会怎样操作

1.首先和上面代码一样定义一个Strategy接口,其中有一个operation的函数交给具体业务去实现

2.根据自己的业务,会拥有很多的策略类实现该接口;将这些类注册到spring Bean容器中提供使用。

3。通过客户端传值,从spring容器中获取Strategy实例

4.最终来执行operation函数

 

参考博客:https://blog.csdn.net/qq1037893644/article/details/102681593

 

标签: 设计模式

目录
相关文章
|
canal 缓存 NoSQL
面试官,如何保证缓存与数据库的数据一致性
面试官,如何保证缓存与数据库的数据一致性
|
Go 开发者
错误处理不再难!Go语言错误处理完全指南
错误处理不再难!Go语言错误处理完全指南
463 0
|
存储 消息中间件 JSON
DDD基础教程:一文带你读懂DDD分层架构
DDD基础教程:一文带你读懂DDD分层架构
|
canal 缓存 NoSQL
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
根据对一致性的要求程度,提出多种解决方案:同步删除、同步删除+可靠消息、延时双删、异步监听+可靠消息、多重保障方案
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
|
11月前
|
存储 监控 数据可视化
常见的分布式定时任务调度框架
分布式定时任务调度框架用于在分布式系统中管理和调度定时任务,确保任务按预定时间和频率执行。其核心概念包括Job(任务)、Trigger(触发器)、Executor(执行器)和Scheduler(调度器)。这类框架应具备任务管理、任务监控、良好的可扩展性和高可用性等功能。常用的Java生态中的分布式任务调度框架有Quartz Scheduler、ElasticJob和XXL-JOB。
4079 66
|
运维 供应链 监控
一文带你了解什么是TOGAF?及TOGAF的应用?
TOGAF(The Open Group Architecture Framework)是由The Open Group组织开发的企业架构框架,提供了一套方法论、工具和术语,帮助企业设计、规划、实施和管理企业架构。其核心是架构开发方法(ADM),涵盖从架构愿景到实施的各个阶段。TOGAF支持跨部门协作、持续改进和项目成功,适用于新系统开发、系统升级、业务流程优化和组织变革管理等场景。
2582 1
一文带你了解什么是TOGAF?及TOGAF的应用?
|
NoSQL 安全 Java
解决Unknown redis exception及event executor terminated错误的方法
解决这类问题时,保持耐心和细致是关键。通常,通过系统地检查和排除潜在原因,大多数问题最终都能被解决。
2115 1
|
消息中间件 运维 数据库
架构设计之解析CQRS架构模式!
架构设计之解析CQRS架构模式!
418 1
架构设计之解析CQRS架构模式!
|
负载均衡 监控 Java
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
25331 7
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
|
缓存 Oracle 关系型数据库
分布式系统详解--基础知识(并发)
分布式系统详解--基础知识(并发)
373 0