当前位置: 首页 > news >正文

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

文章目录

    • 创建design-demo项目
      • 创建UserController
      • 创建UserService
      • 创建UserServiceImpl
      • 创建TicketBuilder
      • 创建PersonalTicketBuilder
      • 创建CompanyTicketBuilder
      • 创建CompanyTicket
      • 创建PersonalTicket
      • 创建TicketConstant
      • 校验是否正常工作

创建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);
    }

}

创建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);
}

创建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();
    }
}

创建TicketBuilder

代码如下(示例):

package com.example.designdemo.ticket.builder;
/**
 * @Author: zhiwei Liao
 * @Date: 2022/9/29 21:29
 * @Description:
 */
public abstract class TicketBuilder<T> {
    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();
}

创建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<PersonalTicket> {

    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;
    }
}

创建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<CompanyTicket> {

    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;
    }
}

创建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;
    }
}

创建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;
    }
}

创建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");
    }
}

校验是否正常工作

在这里插入图片描述

在这里插入图片描述

相关文章:

  • 【关于Linux中权限管理】
  • Opencv项目实战:11 使用Opencv高亮显示文本检测
  • 零基础转行,入职军工类测试方向,月薪10K | 既然选择了,就要全力以赴
  • python字典与集合还有数据类型转换
  • CH559L单片机ADC多通道采样数据串口打印案例
  • 2022保研夏令营/预推免记录:浙大计院直博/西湖电子直博/南大软院/厦大信院
  • windows域KCC知识点
  • 优化树莓派上的网站:免费申请SSL证书 3/4
  • 深度学习梯度下降优化算法(AdaGrad、RMSProp、AdaDelta、Adam)(MXNet)
  • 2022 最新的 Java 八股文合集来了,彻底解决各大大厂面试难题
  • 【SSM框架】Mybatis详解11(源码自取)之事务,缓存,ORM
  • Maven 基本使用及依赖管理。
  • 数组是内存的实现及栈和队列的数据结构
  • 记录:2022-9-30 打家劫舍 二叉搜索树中第K小的元素 公平锁 磁盘调度
  • 基于html宠物用品商城项目的设计与实现(学生网页设计作业源码)
  • 《深入 React 技术栈》
  • Idea+maven+scala构建包并在spark on yarn 运行
  • JavaScript实现分页效果
  • Js基础知识(四) - js运行原理与机制
  • Linux快速复制或删除大量小文件
  • MySQL用户中的%到底包不包括localhost?
  • Nodejs和JavaWeb协助开发
  • Puppeteer:浏览器控制器
  • Rancher-k8s加速安装文档
  • 程序员该如何有效的找工作?
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 小试R空间处理新库sf
  • 用jquery写贪吃蛇
  • NLPIR智能语义技术让大数据挖掘更简单
  • 回归生活:清理微信公众号
  • ​水经微图Web1.5.0版即将上线
  • # C++之functional库用法整理
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #if和#ifdef区别
  • #includecmath
  • ${ }的特别功能
  • ()、[]、{}、(())、[[]]命令替换
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (4.10~4.16)
  • (八)c52学习之旅-中断实验
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (四)库存超卖案例实战——优化redis分布式锁
  • ****Linux下Mysql的安装和配置
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .net 提取注释生成API文档 帮助文档
  • .net知识和学习方法系列(二十一)CLR-枚举
  • /usr/bin/env: node: No such file or directory
  • @RestController注解的使用
  • [ 环境搭建篇 ] 安装 java 环境并配置环境变量(附 JDK1.8 安装包)
  • [AI]文心一言出圈的同时,NLP处理下的ChatGPT-4.5最新资讯
  • [BZOJ 3282] Tree 【LCT】
  • [BZOJ4337][BJOI2015]树的同构(树的最小表示法)
  • [C#]DataTable常用操作总结【转】
  • [C#]科学计数法(scientific notation)显示为正常数字