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

相关推荐
洛小豆11 分钟前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
八怪11 分钟前
联合索引使用高分区度字段的一个例子
后端
IT_陈寒12 分钟前
JavaScript 性能优化:5 个被低估的 V8 引擎技巧让你的代码快 200%
前端·人工智能·后端
惯导马工18 分钟前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
前端小张同学34 分钟前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole39 分钟前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊1 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端
bobz9651 小时前
ebpf 应用于 qemu vm vTAP
后端
bobz9651 小时前
ebpf 直接为虚拟机 tap 网卡提供 零 copy
后端
bobz9651 小时前
ovs vTap 虚拟机场景中,镜像流量可以使用 ebpf 来实现,而非基于 ovs
后端