210816-实战小技巧6:枚举的特殊用法

文章目录
  1. 1. 单例模式
  2. 2. 策略模式
  3. 3. 小结
  4. 4. 实战系列推荐
  • II. 其他
    1. 1. 一灰灰Blog: https://liuyueyi.github.io/hexblog
    2. 2. 微信公众号: 一灰灰blog
  • 每天一个实战小技巧:枚举的特殊用法

    难道我们日常使用的枚举还有什么特殊的玩法不成?没错,还真有,本文主要介绍枚举的两种不那么常见的使用姿势

    • 利用枚举来实现单例模式
    • 利用枚举来实现策略模式

    1. 单例模式

    单例模式可以说是每个java开发者必须掌握的一个设计模式了,通常我们说它的实现,有饱汉式和饿汉式,也有经常说的双重判断,今天我们介绍另外一种方式,借助枚举来实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public enum SingleEnum {
    INSTANCE;

    public void print(String word) {
    System.out.println(word);
    }
    }

    @Test
    public void testSingle() {
    SingleEnum.INSTANCE.print("hello world");
    }

    使用枚举来实现单例模式非常非常简单,将类声明为枚举,内部只定义一个值即可

    为什么可以这样做?

    • 枚举类不能new,因此保证单例
    • 枚举类不能被继承
    • 类不加载时,不会实例化

    使用枚举类创建的单例有一个好处,就是即使用反射,也无法打破它的单例性质,这是相比较于其他的实现方式的一个优点

    那么,为啥在实际的项目中,不太常见这种写法?

    • 就我个人的一点认知(不保证准确):这个与我们对枚举的认知有一定关系,在 《Effect in java》一书中,推荐我们使用这种方式来实现单例,但是在实际的项目开发中,我们更多的将枚举作为常量来使用,很少在枚举类中,添加复杂的业务逻辑

    2. 策略模式

    枚举除了很容易就实现上面的单例模式之外,还可以非常简单的实现策略模式

    举一个简单的例子,我现在有一个接口,通过接受的参数,来决定最终的数据存在什么地方

    如果按照正常的写法,可能就是很多的if/else

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public void save(String type, Object data) {
    if ("db".equals(type) {
    // 保存到db
    saveInDb(data);
    } else if ("file".equals(type))
    // 保存在文件
    saveInFile(data);
    } else if ("oss".eqauls(type)) {
    // 保存在oss
    saveInOss(type);
    }
    }

    上面这种写法虽说简单直观,但是当type类型一多了之后,这个if/else的代码行数就会很多很多了,而且看起来也不美观

    接下来我们介绍一种利用枚举,基于策略模式的思想来解决上面的if/else问题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    public enum SaveStrategyEnum {
    DB("db") {
    @Override
    public void save(Object obj) {
    System.out.println("save in db:" + obj);
    }
    },
    FILE("file") {
    @Override
    public void save(Object obj) {
    System.out.println("save in file: " + obj);
    }
    },
    OSS("oss") {
    @Override
    public void save(Object obj) {
    System.out.println("save in oss: " + obj);
    }
    };

    private String type;

    SaveStrategyEnum(String type) {
    this.type = type;
    }

    public abstract void save(Object obj);

    public static SaveStrategyEnum typeOf(String type) {
    for (SaveStrategyEnum strategyEnum: values()) {
    if (strategyEnum.type.equalsIgnoreCase(type)) {
    return strategyEnum;
    }
    }
    return null;
    }
    }

    public void save(String type, Object data) {
    SaveStrategyEnum strategyEnum = SaveStrategyEnum.typeOf(type);
    if (strategyEnum != null) {
    strategyEnum.save(data);
    }
    }

    上面的实现,主要利用的是抽象类 + 枚举来完成不同的策略具体实现

    这种实现方式,相比较与前面的单例模式,还是更常见一点,虽然整体看下来没有什么难度,但是仔细看一看,会发现几个知识点

    • 抽象方法的使用 (在模板设计模式中,更能体会抽象方法的使用妙处)
    • 利用枚举原生提供的values(),来实现遍历,找到目标

    3. 小结

    枚举虽然说是jdk原生提供的一个基础数据类型,但是它的使用姿势除了我们熟知的常量之外,还可以有效的运用在设计模式中,让我们的代码实现更优雅

    比如使用枚举来实现单例模式,就不用再面对让人烦躁的双重判断/内部类的方式了

    使用枚举的策略模式,也可以有效解决我们类中大量的if/else

    4. 实战系列推荐

    II. 其他

    1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

    一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

    2. 微信公众号: 一灰灰blog

    尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

    • 微博地址: 小灰灰Blog
    • QQ: 一灰灰/3302797840
    • 微信公众号: 一灰灰blog

    QrCode

    评论

    Your browser is out-of-date!

    Update your browser to view this website correctly. Update my browser now

    ×