• 【设计模式】【第五章】【开具增值税发票】【建造者模式 + 原型模式】


    创建design-demo项目

    项目代码:https://gitee.com/java_wxid/java_wxid/tree/master/demo/design-demo
    项目结构如下(示例):
    在这里插入图片描述

    创建UserController

    代码如下(示例):

    package com.example.designdemo.controller;
    
    import com.example.designdemo.pojo.TicketParam;
    import com.example.designdemo.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    /**
     * @Author: zhiwei Liao
     * @Date: 2022/9/25 19:26
     * @Description:
     */
    @RestController
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @PostMapping("/ticket")
        public Object getTicket(@RequestBody TicketParam ticketParam) {
            return userService.getTicket(ticketParam);
        }
    
    }
    
    
    • 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

    创建UserService

    代码如下(示例):

    package com.example.designdemo.service;
    
    import com.example.designdemo.pojo.TicketParam;
    
    
    /**
     * @Author: zhiwei Liao
     * @Date: 2022/9/25 9:28
     * @Description:
     */
    
    public interface UserService {
    
        Object getTicket(TicketParam ticketParam);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    创建UserServiceImpl

    代码如下(示例):

    package com.example.designdemo.service.impl;
    
    import com.example.designdemo.handler.SuggestRequirementHandlerProcess;
    import com.example.designdemo.pojo.TicketParam;
    import com.example.designdemo.pojo.UserInfo;
    import com.example.designdemo.service.UserService;
    import com.example.designdemo.ticket.builder.CompanyTicketBuilder;
    import com.example.designdemo.ticket.builder.PersonalTicketBuilder;
    import com.example.designdemo.ticket.builder.TicketBuilder;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private SuggestRequirementHandlerProcess suggestRequirementHandlerProcess;
    
        //因为这部分是需要查询 缓存(如果缓存没有,需要查库)不应该写到 service层,但是为了代码书写简便
        //这部分我模拟在service 层。
        private UserInfo getUserInfo(String username) {
            return new UserInfo();
        }
    
        public Object getTicket(TicketParam ticketParam) {
            TicketBuilder builder = null;
            String bankInfo = null;
            if(ticketParam.getBankInfo() != null) {
                bankInfo = "from 3rd party interface check.";
                builder = new CompanyTicketBuilder();
            } else {
                builder = new PersonalTicketBuilder();
            }
            builder.setParam(ticketParam.getAccount(), ticketParam.getTitle());
            String content = "from config center";
            String product = "from db";
            builder.setContent(content);
            builder.setProduct(product);
            builder.setBankInfo(bankInfo);
            // 详细的逻辑细节控制以及从配置中心或者是db中获取的逻辑步骤就是简单的 crud,自己明白即可
            return  builder.buildTicket();
        }
    }
    
    
    • 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

    创建TicketBuilder

    代码如下(示例):

    package com.example.designdemo.ticket.builder;
    /**
     * @Author: zhiwei Liao
     * @Date: 2022/9/29 21:29
     * @Description:
     */
    public abstract class TicketBuilder {
        public abstract void setParam(String account, String title);
    
        public abstract void setContent(String content); // 配置中心 或 DB 或缓存
        public abstract void setProduct(String product); // db
        public void setBankInfo(String bankInfo){}; //需要校验的,校验通过才能设置
    
        public abstract T buildTicket();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    创建PersonalTicketBuilder

    代码如下(示例):

    package com.example.designdemo.ticket.builder;
    
    
    import com.example.designdemo.ticket.TicketConstant;
    import com.example.designdemo.ticket.pojo.PersonalTicket;
    /**
     * @Author: zhiwei Liao
     * @Date: 2022/9/29 21:29
     * @Description:
     */
    public class PersonalTicketBuilder extends TicketBuilder {
    
        private PersonalTicket personalTicket = TicketConstant.personalTicket.clone(); // new 关键字 改成clone的形式,只clone我们的
        // 不可变部分。对于可变部分和自定义用户提交部分,不进行clone
    
        @Override
        public void setParam(String account, String title) {
            personalTicket.setTitle(title);
            personalTicket.setAccount(account);
        }
    
        @Override
        public void setContent(String content) {
            personalTicket.setContent(content);
        }
    
        @Override
        public void setProduct(String product) {
            personalTicket.setProduct(product);
        }
    
        @Override
        public PersonalTicket buildTicket() {
            return personalTicket;
        }
    }
    
    
    • 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

    创建CompanyTicketBuilder

    代码如下(示例):

    package com.example.designdemo.ticket.builder;
    
    
    import com.example.designdemo.ticket.TicketConstant;
    import com.example.designdemo.ticket.pojo.CompanyTicket;
    /**
     * @Author: zhiwei Liao
     * @Date: 2022/9/29 21:29
     * @Description:
     */
    public class CompanyTicketBuilder extends TicketBuilder {
    
        private CompanyTicket companyTicket = TicketConstant.companyTicket.clone(); // new 关键字
    
        @Override
        public void setBankInfo(String bankInfo) {
            companyTicket.setBankInfo(bankInfo);
        }
    
        @Override
        public void setParam(String account, String title) {
            companyTicket.setTitle(title);
            companyTicket.setAccount(account);
        }
    
        @Override
        public void setContent(String content) {
            companyTicket.setContent(content);
        }
    
        @Override
        public void setProduct(String product) {
            companyTicket.setProduct(product);
        }
    
        @Override
        public CompanyTicket buildTicket() {
            return companyTicket;
        }
    }
    
    
    • 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

    创建CompanyTicket

    代码如下(示例):

    package com.example.designdemo.ticket.pojo;
    /**
     * @Author: zhiwei Liao
     * @Date: 2022/9/29 21:29
     * @Description:
     */
    public class CompanyTicket implements Cloneable{
        private String type;
        private String footer;
    
        private String content; //配置中心 或者 DB里边获取。(缓存里获取,只不过如果万一DB 或配置中心有修改,需要同时更新缓存)
        private String product; //大部分情况db里获取(缓存里是有一些热门产品的)
        private String bankInfo; //校验我们的银行卡信息(通过我们的第三方银行相关接口进行的校验)
    
        private String account;
        private String title;
    
        public String getFooter() {
            return footer;
        }
    
        public void setFooter(String footer) {
            this.footer = footer;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        public String getAccount() {
            return account;
        }
    
        public void setAccount(String account) {
            this.account = account;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public String getProduct() {
            return product;
        }
    
        public void setProduct(String product) {
            this.product = product;
        }
    
        public String getBankInfo() {
            return bankInfo;
        }
    
        public void setBankInfo(String bankInfo) {
            this.bankInfo = bankInfo;
        }
    
        @Override
        public CompanyTicket clone() {
            CompanyTicket companyTicket = null;
            try {
                companyTicket = (CompanyTicket) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return companyTicket;
        }
    }
    
    
    • 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
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    创建PersonalTicket

    代码如下(示例):

    package com.example.designdemo.ticket.pojo;
    /**
     * @Author: zhiwei Liao
     * @Date: 2022/9/29 21:29
     * @Description:
     */
    public class PersonalTicket implements Cloneable{
        private String type;
        private String footer;
    
        private String content; //配置中心 或者 DB里边获取。(缓存里获取,只不过如果万一DB 或配置中心有修改,需要同时更新缓存)
        private String product; //大部分情况db里获取(缓存里是有一些热门产品的)
    
        private String account; // 接口入参获取
        private String title;  // 接口入参获取
    
        public String getFooter() {
            return footer;
        }
    
        public void setFooter(String footer) {
            this.footer = footer;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        public String getAccount() {
            return account;
        }
    
        public void setAccount(String account) {
            this.account = account;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public String getProduct() {
            return product;
        }
    
        public void setProduct(String product) {
            this.product = product;
        }
    
        @Override
        public PersonalTicket clone() {
            PersonalTicket personalTicket = null;
            try {
                personalTicket = (PersonalTicket) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return personalTicket;
        }
    }
    
    
    • 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
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    创建TicketConstant

    代码如下(示例):

    package com.example.designdemo.ticket;
    
    
    import com.example.designdemo.ticket.pojo.CompanyTicket;
    import com.example.designdemo.ticket.pojo.PersonalTicket;
    
    public class TicketConstant {
        // 保存只具有公共属性的对象,供clone使用。
        public static PersonalTicket personalTicket = new PersonalTicket();
        public static CompanyTicket companyTicket = new CompanyTicket();
    
        static {
            personalTicket.setType("type");
            personalTicket.setFooter("footer");
            companyTicket.setType("type");
            companyTicket.setFooter("footer");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    校验是否正常工作

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    广和通入驻中国联通5G物联网OpenLab开放实验室,携手共赴5G扬帆新征程
    linux系统安全配置命令详解
    获取spring容器中的bean实例
    Docker搭建DNS服务器--nouse
    bootstrap学习:bootstrap定制化 根据bootstrap实现自己的Ui库
    docker 安装mysql8
    PHP正则表达式(匹配手机号码、邮箱、img中的src值)
    PHP跌出前十,Python依然霸占榜首,C#有望摘得年度编程语言 TIOBE 12 月编程语言排行榜
    JD(按关键字搜索商品)API接口
    【Python】Python 网络编程 ( Socket 套接字简介 | Socket 套接字使用步骤 | Socket 套接字服务端与客户端开发 )
  • 原文地址:https://blog.csdn.net/java_wxid/article/details/127128651