【版本任你发】-3-封装并复用if判断逻辑,变动时统一修改

1,282 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

0.背景

  通常,我们在编写业务逻辑的时候,会遇到很多类似的判断逻辑。下面,我们以给用户送礼物为例,来给大家做一个封装。

1.给用户发优惠券

  假设,我们的用户 id 为一个 int 值的流水号。从1开始编写的,现在不是2022年了吗?咱们快餐店店庆了,老板发话了,要给所有id是20的倍数的用户发一个1分钱的优惠券。于是,程序员小孙很平淡地写下:

public class OriginalTest {

    static class User {

        private int id;

        public int getId() {
            return id;
        }

        public User(int id) {
            this.id = id;
        }
    }

    public static void main(String[] args) {
        User user = new User(20);
        if (user.getId() % 20 == 0) {
            System.out.println("恭喜您获得一张1分钱优惠券");
        }
    }

}

  没一会儿,挠头的老板又发话了:“我刚才没想好,今年不是22结尾的吗?再给所有id是22的倍数的用户发一个2分钱的优惠券”。小孙无奈地说:“那好吧,我改改。”

public class OriginalTest {

    static class User {

        private int id;

        public int getId() {
            return id;
        }

        public User(int id) {
            this.id = id;
        }
    }

    public static void main(String[] args) {
        User user = new User(22);
        if (user.getId() % 20 == 0) {
            System.out.println("恭喜您获得一张1分钱优惠券");
        }
        if (user.getId() % 22 == 0) {
            System.out.println("恭喜您获得一张2分钱优惠券");
        }
    }

}

  还没完,老板拍了拍头,然后和小孙说:“上线了吗?再加一个规则,同时为20和22的倍数的,不仅发这些优惠券,再发一个头像挂件。”小孙撇撇嘴:“那好吧,我改”

public class OriginalTest {

    static class User {

        private int id;

        public int getId() {
            return id;
        }

        public User(int id) {
            this.id = id;
        }
    }

    public static void main(String[] args) {
        User user = new User(220);
        if (user.getId() % 20 == 0) {
            System.out.println("恭喜您获得一张1分钱优惠券");
        }
        if (user.getId() % 22 == 0) {
            System.out.println("恭喜您获得一张2分钱优惠券");
        }
        if (user.getId() % 20 == 0 && user.getId() % 22 == 0) {
            System.out.println("恭喜您获得一个头像挂件");
        }
    }

}

  老板看着小孙写的程序,非常满意。转头去折磨程序员小黄:“那个什么,你是管理订单的吧,咱们新的订单号,如果出现了是20的倍数,发一张一分钱优惠券。”

  小黄有点犯难,他找到了小孙:“怎么做啊?你有什么写好的代码吗?”

  小孙反驳道:“你是订单部,我是用户部,代码能乱用吗?”

  小黄有点生气:“你又不是不知道老板,就这临时需求,能保持到明天就不错!”

  小孙有点不耐烦:“得得得,我提取个公共工具类好吧。”

public class UtilTest {

    static class User {

        private int id;

        public int getId() {
            return id;
        }

        public User(int id) {
            this.id = id;
        }
    }

    static class DiscountCouponUtil {

        public static boolean oneCent(int number) {
            if (number % 20 == 0) {
                return true;
            }
            return false;
        }

        public static boolean twoCents(int number) {
            if (number % 22 == 0) {
                return true;
            }
            return false;
        }

        public static boolean headPendant(int number) {
            return oneCent(number) && twoCents(number);
        }
    }

    public static void main(String[] args) {
        User user = new User(220);
        int userId = user.getId();
        if (DiscountCouponUtil.oneCent(userId)) {
            System.out.println("恭喜您获得一张1分钱优惠券");
        }
        if (DiscountCouponUtil.twoCents(userId)) {
            System.out.println("恭喜您获得一张2分钱优惠券");
        }
        if (DiscountCouponUtil.headPendant(userId)) {
            System.out.println("恭喜您获得一个头像挂件");
        }
    }

}

2.给用户发幸运大礼包

  就在代码要上线的时候,老板急匆匆跑到了 荡平宇宙软件开发部 ,大声喊:“我刚才一拍大腿,想到个事儿。咱们要给用户id以20为倍数的,或者以22为倍数的人再发一个幸运大礼包。你们临时改一下,我马上要!”

  小孙说:“这可如何是好啊,代码都乱套了都!屎山雕花呢,现在!”老板拍了拍胸脯:“我保证是最后一次修改了,行了,行了,赶紧干吧。”

  坐在一旁的老安听到了小孙的吐槽,他问小孙怎么回事儿。小孙把经过告诉了他,他笑着说:“你用Predicate 可以让情绪好一点。” 小孙瞪大眼睛:“啥?啥Cate?”

  老安不慌不忙地帮他改代码:“我们先写一个判断的类”

public class DiscountCouponPredicateUtil {

    public static class DividedByTwenty implements Predicate<Integer> {

        @Override
        public boolean test(Integer integer) {
            if (integer % 20 == 0) {
                return true;
            }
            return false;
        }
    }

    public static class DividedByTwentyTwo implements Predicate<Integer> {

        @Override
        public boolean test(Integer integer) {
            if (integer % 22 == 0) {
                return true;
            }
            return false;
        }
    }

}

  然后我们在业务代码里使用他们。

public class PredicateTest {

    static class User {

        private int id;

        public int getId() {
            return id;
        }

        public User(int id) {
            this.id = id;
        }
    }

    private static final DiscountCouponPredicateUtil.DividedByTwenty DIVIDED_BY_TWENTY_PRE = new DiscountCouponPredicateUtil.DividedByTwenty();

    private static final DiscountCouponPredicateUtil.DividedByTwentyTwo DIVIDED_BY_TWENTY_TWO_PRE = new DiscountCouponPredicateUtil.DividedByTwentyTwo();


    public static void main(String[] args) {
        User user = new User(220);
        int userId = user.getId();
        if (DIVIDED_BY_TWENTY_PRE.test(userId)) {
            System.out.println("恭喜您获得一张1分钱优惠券");
        }
        if (DIVIDED_BY_TWENTY_TWO_PRE.test(userId)) {
            System.out.println("恭喜您获得一张2分钱优惠券");
        }
        if (DIVIDED_BY_TWENTY_PRE.and(DIVIDED_BY_TWENTY_TWO_PRE).test(userId)) {
            System.out.println("恭喜您获得一个头像挂件");
        }
        if (DIVIDED_BY_TWENTY_PRE.or(DIVIDED_BY_TWENTY_TWO_PRE).test(userId)) {
            System.out.println("恭喜您获得一个幸运大礼包");
        }
    }

}

  小孙惊讶道:“确实逻辑感更好一点,这个 Predicate 还有什么好处呢?”

  老安笑着说:“当然有了,你可以将相关的判断逻辑整理在一起,如果是长期存在的需求,修改的时候也很好改。比如……”

  正说着,老板急匆匆地跑过来:“我刚才一拍头啊,想出一个绝妙的点子。我们何不搞一个幸运号的长期活动?每年改一改幸运号的规则,但是年年都可以搞幸运号活动,让用户像期待集五福一样期待幸运号活动。”

  老安笑着说:“小孙啊,这个幸运号,可以写成一个Predicate,所有用到的地方可以引用。第二年发生变更时,就可以统一进行修改了。”

public class DiscountCouponPredicateUtil {

    public static class LuckyNumberPredicate implements Predicate<Integer> {
        
        @Override
        public boolean test(Integer integer) {
            if (integer % 20 == 0 && integer % 22 == 0) {
                return true;
            }
            return false;
        }
    }

}

  老板看到老安笑了,自己也笑着说:“很好改?是吗?一会儿能上线吗?”

  办公室再一次陷入了安静……

结语

  本例中,我们学习了如何提取判断逻辑,如何统一修改业务判断上表达业务含义一致的逻辑代码。这是 Java8 给我们封装、复用判断逻辑的利器。

  读者朋友,你有什么想要分享的,好的 Predicate 的应用呢?欢迎你在评论区和其他读者讨论!