【中秋赏码】Java程序员用中文编程教你做月饼。

【中秋赏码】Java程序员用中文编程教你做月饼。_第1张图片

一、前言

什么? 花好月圆之日你还在写Bug? 什么? 花好月圆之日你还在加班? 什么? 花好月圆之日你还没有女朋友?

没关系我也没有。不过还好, 至少公司还发了一盒月饼。那我们就开始赏月吧。等等… 我们的主题是中秋赏码。

本篇小编教你用中文写出具有中国特色的制造月饼的代码工艺吧, 我们中秋赏码。在赏码的过程中,顺便学习几个设计模式。来看看有几个是你平时常用的吧。

【中秋赏码】Java程序员用中文编程教你做月饼。_第2张图片

需求是这样的:

有一个食品车间,中秋卖月饼,端午卖粽子。这不马上到中秋了嘛。今年一共会生产3种口味的月饼。【五仁月饼】【莲蓉蛋黄月饼】【枣泥月饼】。交给你来设计系统,你会怎么设计呢?

需求设计

那么我们如何使用设计模式来生产月饼呢? 在聊设计模式之前我们先思考下如何高效做月饼? 最后再用设计模式进行优化。

首先我们先定义一个食品工厂,食品工厂不可能只卖月饼,中秋卖月饼,端午卖粽子。至于让工厂生产什么,却绝于季节,所以我们要定义一个策略【策略模式】。

【中秋赏码】Java程序员用中文编程教你做月饼。_第3张图片

每个食品车间,生产的食品,味道可能也是不同的,食品加工工艺也是不同的。为每个食品车间定义一个流水线接口, 相同食品一定会有通用的操作流程,所以定义一个标准的月饼生产模版类,模版类中提供通用的流程。

【中秋赏码】Java程序员用中文编程教你做月饼。_第4张图片

具体的口味只是生产月饼中的步骤的不同,所以交给子类来实现。

所以最终这里我们会用到三种设计模式。

  • 工厂模式 + 策越模式
  • 抽象模版

二、中秋赏码

2.1 目录结构

源码仓库地址

.
├── main
│   ├── java
│   │   └── cn
│   │       └── lxchinesszz
│   │           ├── 流水线
│   │           │   ├── 五仁月饼流水线.java
│   │           │   ├── 月饼制作流水线.java
│   │           │   ├── 月饼流水线.java
│   │           │   ├── 枣泥月饼流水线.java
│   │           │   ├── 流水线.java
│   │           │   └── 莲蓉蛋黄月饼流水线.java
│   │           ├── 车间
│   │           │   ├── 月饼生产车间.java
│   │           │   └── 食品车间.java
│   │           ├── 食品
│   │           │   ├── 食品.java
│   │           │   └── 月饼.java
│   │           ├── 食品口味.java
│   │           └── 食品工厂.java
│   └── resources
└── test
    └── java

2.2 定义食品工厂

关键字: 策略模式

具体工厂生产什么,由使用方自己决定。

public class 食品工厂 {

    private 食品车间 车间;

    public 食品工厂(食品车间 车间) {
        this.车间 = 车间;
    }

    public 食品 生产食品(食品口味 口味) {
        return 车间.生产食品(口味);
    }
}

2.3 定义食品车间

关键字: 口味策略

public interface 食品车间 {
    食品 生产食品(食品口味 口味);
}

public class 月饼生产车间 implements 食品车间 {
    @Override
    public 食品 生产食品(食品口味 口味) {
        流水线 月饼流水线;
        if (食品口味.五仁.equals(口味)) {
            月饼流水线 = new 五仁月饼流水线();
        } else if (食品口味.枣泥.equals(口味)) {
            月饼流水线 = new 枣泥月饼流水线();
        } else {
            月饼流水线 = new 莲蓉蛋黄月饼流水线();
        }
        System.out.println("月饼车间开工了,开始生产月饼了");
        食品 月饼 = 月饼流水线.生成食品();
        System.out.println("【" + 月饼 + "】,生产好了");
        return 月饼;
    }
}

2.4 定义流水线

关键字: 抽象模版

月饼流水线实现了流水线的生产食品的接口, 并提供抽象的生产月饼的接口。交给子类去使用。在模版类中
可以定义统一的月饼生产流程。而具体月饼口味的细节交给子类去实现。

public interface 流水线{
    食品 生成食品();
}

public abstract class 月饼流水线 implements 流水线 {
    @Override
    public 食品 生成食品() {
        System.out.println("月饼生产作业开始:和面");
        食品 食品 = 生成月饼();
        System.out.println("月饼烤制流程结束");
        System.out.println("开始烤制完成开始打包装箱");
        return 食品;
    }
    public abstract 食品 生成月饼();
}

2.5 具体口味实现

关键字: 单一职责

月饼中口味的不同,交给子类的具体的实现,每种口味之间没有依赖关系。完全的解耦。

  • 五仁月饼
public class 五仁月饼流水线 extends 月饼流水线 {
    @Override
    public 月饼 生成月饼() {
        System.out.println("开始生成五仁月饼");
        return new 月饼(食品口味.五仁);
    }
}
  • 枣泥月饼
public class 枣泥月饼流水线 extends 月饼流水线 {
    @Override
    public 月饼 生成月饼() {
        System.out.println("开始生成枣泥月饼");
        return new 月饼(食品口味.枣泥);
    }
}
  • 莲蓉蛋黄月饼
public class 莲蓉蛋黄月饼流水线 extends 月饼流水线 {
    @Override
    public 月饼 生成月饼() {
        System.out.println("开始生成莲蓉蛋黄月饼");
        return new 月饼(食品口味.莲蓉蛋黄);
    }
}

三、总结

我们的设计的时候,可以思考这些地方。在这些地方进行优化和设计。

  1. 单一职责,高内聚低耦合,一个类只做一个事情,尽量避免耦合。
  2. 接口是自上而下设计的,你想要的能力究竟是什么?
  3. 抽象是自下而上设计的,千万不要搞反了,能公用的或者是能抽象出标准流程的可以使用模版来定义。
  4. 考虑扩展性。暂时想不到可以不考虑,没必要为了扩展性的而天马行空的去设计,得不偿失。

只要记住这几个知识点,相信你的设计能力也会有很大的提升。下面我们来解释这几句话。各位观众老爷如果还有设计的小妙招,欢迎留言评论。

3.1 单一职责,接口设计

月饼口味的设计,每种口味的做法是不相同的,所以我们先定义一个生产月饼的接口。具体的实现都是细节,
每种口味的要保持单一职责,这样的好处是,当你再修改一个口味的时候,是一定不会影响到其他口味的月饼生成的。

如果只考虑这些可能我们的图就像下面这样。

【中秋赏码】Java程序员用中文编程教你做月饼。_第5张图片

public class 五仁月饼流水线 extends 月饼流水线 {
    @Override
    public 月饼 生成月饼() {
        System.out.println("开始生成五仁月饼");
        return new 月饼(食品口味.五仁);
    }
}
public class 枣泥月饼流水线 extends 月饼流水线 {
    @Override
    public 月饼 生成月饼() {
        System.out.println("开始生成枣泥月饼");
        return new 月饼(食品口味.枣泥);
    }
}
public class 莲蓉蛋黄月饼流水线 extends 月饼流水线 {
    @Override
    public 月饼 生成月饼() {
        System.out.println("开始生成莲蓉蛋黄月饼");
        return new 月饼(食品口味.莲蓉蛋黄);
    }
}

3.2 抽象是自下而上设计的

抽象是自下而上设计,不可能在不清楚细节的情况下,上去就进行抽象的。而一定是在细节已经设计好了的情况下,再进行抽象来优化流程。

所以我们思考: 不管月饼的口味是什么,他们都是月饼。一定有最终相同的处理流程。比如说月饼包装,月饼都需要进行烤制。这个时候我们就要在这三种口味的月饼上进行抽象了,他们有什么相同点? 相同点都抽象出来,形成标准的模版。
所以我们在上面设计一个抽象类,抽象类中做公用的逻辑。

【中秋赏码】Java程序员用中文编程教你做月饼。_第6张图片

就如果上面的代码,我们在抽象类中,去和面、烤制、和打包装箱。

public abstract class 月饼流水线 implements 流水线 {
    @Override
    public 食品 生成食品() {
        System.out.println("月饼生产作业开始:和面");
        食品 食品 = 生成月饼();
        System.out.println("月饼烤制流程结束");
        System.out.println("开始烤制完成开始打包装箱");
        return 食品;
    }

    public abstract 食品 生成月饼();
}

3.3 考虑扩展性

工厂不可能只生成月饼,这里使用策略设计,生产什么你说了算。

public class 食品工厂 {

    private 食品车间 车间;

    public 食品工厂(食品车间 车间) {
        this.车间 = 车间;
    }

    public 食品 生产食品(食品口味 口味) {
        return 车间.生产食品(口味);
    }

    public static void main(String[] args) {
        new 食品工厂(new 月饼生产车间()).生产食品(食品口味.枣泥);
    }

}

那么你get到,你想要的知识点了吗? 那么你准备好跟我一起Coding了吗?

【中秋赏码】Java程序员用中文编程教你做月饼。_第7张图片


推荐环节

最后小编还写了免费的关于Mybatis的源码学习系列和手撸JavaRPC系列,从网络通信开始,从0到1实现一个RPC框架爱,如果感兴趣的话,点个关注吧,交个朋友吧。

天下代码一大抄,抄来抄去有提高,看你会抄不会抄,跟我一起来写代码吧。

【中秋赏码】Java程序员用中文编程教你做月饼。_第8张图片

  • 第01篇:手写JavaRPC框架之思路分析
  • 第02篇:手写JavaRPC框架之设计思路
  • 第03篇: 手写JavaRPC框架之搞定序列化
  • 第04篇:手写JavaRPC框架之搞定网络通信
  • 第05篇:手写JavaRPC框架之执行层思路

你可能感兴趣的:(java,开发语言)