【设计模式_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:最近的事情太多了,导致断更太久了。先试着写写复健复健。努力保持、每天学习一点点。

相关推荐
_OP_CHEN5 分钟前
【算法基础篇】(五十九)巴什博弈 (Bash Game) 超详解:从原理到实战,搞定经典取石子问题
算法·蓝桥杯·c/c++·博弈论·算法竞赛·acm/icpc·bash博弈
leobertlan8 小时前
2025年终总结
前端·后端·程序员
面向Google编程8 小时前
从零学习Kafka:数据存储
后端·kafka
易安说AI9 小时前
Claude Opus 4.6 凌晨发布,我体验了一整晚,说说真实感受。
后端
易安说AI9 小时前
Ralph Loop 让Claude无止尽干活的牛马...
前端·后端
易安说AI9 小时前
用 Claude Code 远程分析生产日志,追踪 Claude Max 账户被封原因
后端
颜酱10 小时前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法
m0_7369191010 小时前
C++代码风格检查工具
开发语言·c++·算法
yugi98783810 小时前
基于MATLAB强化学习的单智能体与多智能体路径规划算法
算法·matlab
DuHz11 小时前
超宽带脉冲无线电(Ultra Wideband Impulse Radio, UWB)简介
论文阅读·算法·汽车·信息与通信·信号处理