【设计模式_02】使用策略模式实现主键算法的切换

本文主要有以下内容:

  • 策略模式

策略模式:策略模式是一种行为型模式,通常用来定义同一行为或逻辑的不同实现,如主键生成策略的不同算法,

实现方式:

  • 抽取出不同方式完成同特定任务的类,将其共有的逻辑抽取出来定义在被称为策略的独立类或者接口。
  • 在一个称之为上下文的类中保留其策略类的引用,用于替换不同类型的实现。上下文并不执行,而是将其委托给其具体实现类执行。

类图如下:

一个简单的代码示例,策略接口和策略具体实现代码如下:

java 复制代码
public interface Strategy {
    void execute();
}
public class ConcreteStrategyA implements Strategy {
    @Override
    public void execute() {
        log.info("ConcreteStrategy execute: 策略设计模式:具体实现类A");
    }
}
public class ConcreteStrategyB implements Strategy {
    @Override
    public void execute() {
        log.info("ConcreteStrategyB execute:策略设计模式具体实现B");
    }
}

在上下文类中保持对策略的引用。代码如下:

java 复制代码
public class Context {
    private Strategy strategy;
​
    public Context() {
    }
    public void execute() {
        strategy.execute();
    }
}

客户端使用:

java 复制代码
public static void main(String[] args) {
    Context context = new Context();
​
    ConcreteStrategyA strategyA = new ConcreteStrategyA();
    context.setStrategy(strategyA);
​
    context.execute();
    ConcreteStrategyB concreteStrategyB = new ConcreteStrategyB();
    context.setStrategy(concreteStrategyB);
​
    context.execute();
}

在实际的项目开发中。如项目中完成某一个事情有多种方式,就可以采用此设计模式。在Springboot中使用,以主键生成策略为例:主键策略的不同实现:如雪花主键、随机生成主键、短主键。

java 复制代码
public interface IIdGenerator {
    /**
     * 功能: 生成主键
     * @return long
     */
    long nextId();
}

代码的具体实现如下:

java 复制代码
// 随机主键
@Component
public class RandomNumeric implements IIdGenerator {
    @Override
    public long nextId() {
        return Long.parseLong(RandomStringUtils.randomNumeric(11));
    }
}
// 短码主键
@Component
public class ShortCode implements IIdGenerator {
    @Override
    public long nextId() {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int week = calendar.get(Calendar.WEEK_OF_YEAR);
        int day = calendar.get(Calendar.DAY_OF_WEEK);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
​
        // 打乱排序:2024年为准
        StringBuilder idStr = new StringBuilder();
        idStr.append(year - 2024);
        idStr.append(day);
        idStr.append(String.format("%02d", week));
        idStr.append(hour);
        return Long.parseLong(idStr.toString());
    }
}
// 雪花主键
@Component
public class SnowFlake implements IIdGenerator {
    private Snowflake snowflake;
​
    @PostConstruct
    public void init() {
        // 0 ~ 31 位,可以采用配置的方式使用
        long workerId;
        try {
            workerId = NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
        } catch (Exception e) {
            workerId = NetUtil.getLocalhostStr().hashCode();
        }
        workerId = workerId >> 16 & 31;
        long dataCenterId = 1L;
        snowflake = IdUtil.createSnowflake(workerId, dataCenterId);
    }
​
    @Override
    public synchronized long nextId() {
        return snowflake.nextId();
    }
}

建立上下文引用:并通过自动注入的方式注入。

Java 复制代码
// 枚举类
  public enum Ids {
      SnowFlake,
      ShortCode,
      RandomNumeric;
  }
@Configuration
public class IdContext {
    @Bean
    public Map<Constants.Ids, IIdGenerator> idGenerator(SnowFlake snowFlake,
                                                        ShortCode shortCode,
                                                        RandomNumeric randomNumeric) {
        Map<Constants.Ids, IIdGenerator> idGeneratorMap = new HashMap<>(8);
        idGeneratorMap.put(Constants.Ids.SnowFlake, snowFlake);
        idGeneratorMap.put(Constants.Ids.ShortCode, shortCode);
        idGeneratorMap.put(Constants.Ids.RandomNumeric, randomNumeric);
        return idGeneratorMap;
    }
}

接下来就可以在需要使用的地方注入此map,这样就可以在项目中随心所欲的使用了。

ps:最近的事情太多了,导致断更太久了。先试着写写复健复健。努力保持、每天学习一点点。

相关推荐
掘金_答案5 分钟前
上线那天,一个 ConcurrentHashMap 差点送走我的 AI 客服——3 天排查 JVM 血泪史
java·后端·架构
妙码生花10 分钟前
从 PHP 到 AI + Golang,程序员自救转型手记(三十三):权限规则管理器
后端·go·gin
怪兽学LLM11 分钟前
LeetCode 105. 从前序与中序遍历序列构造二叉树:分治递归思路详解
算法·leetcode·职场和发展
可编程芯片开发23 分钟前
基于PI控制的三相整流器控制系统的simulink建模与仿真,包含超级电容充电和电机
算法
酿情师37 分钟前
区块链共识算法深度拆解:PoW、PoS、PBFT、Raft 原理解析
算法·区块链·共识算法
Kim_wang41 分钟前
agent项目部署流程
人工智能·后端
hansang_IR1 小时前
【记录】「SCOI2016」三道模拟赛/26.7.12
c++·算法
退休倒计时1 小时前
【每日一题】LeetCode 39. 组合总和 TypeScript
算法·leetcode·typescript
不是az1 小时前
力控相关知识点
算法·机器学习·最小二乘法
程序员天天困1 小时前
优雅记录操作日志:从注解到 SpEL 的全链路实践与开源方案对比
java·后端