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

相关推荐
lichenyang45323 分钟前
Mongodb(文档数据库)的安装与使用(文档的增删改查)
后端
雨落倾城夏未凉25 分钟前
8.被free回收的内存是立即返还给操作系统吗?为什么?
c++·后端
数新网络25 分钟前
LevelDB 辅助工具类
后端
Code_Artist27 分钟前
[Go]结构体实现接口类型静态校验——引用类型和指针之间的关系
后端·面试·go
onejason28 分钟前
《利用 Python 爬虫获取 Amazon 商品详情实战指南》
前端·后端·python
雨落倾城夏未凉28 分钟前
6.new和malloc的区别
c++·后端
程序员清风1 小时前
跳表的原理和时间复杂度,为什么还需要字典结构配合?
java·后端·面试
AI小白的Python之路1 小时前
数据结构与算法-排序
数据结构·算法·排序算法
用户298698530141 小时前
C#合并/拆分PDF文档的3种方法(Spire.PDF实战示例)
后端
zxhnext1 小时前
LLM大语言模型入门
前端·后端