Java实现月饼的制作、下单和售卖功能
作者:小明java问道之路 发布时间:2023-03-06 18:26:24
本文导读
中秋节是中国民间的传统节日,中秋节源自天象崇拜由上古时代秋夕祭月演变而来。中秋节自古便有祭月、赏月、吃月饼等民俗,流传至今,经久不息。
说到月饼,我们现在吃的都是工厂、小作坊、自己家里制作,在电商平台售卖或者有一些营销活动赠送,我们来看看Java是怎么制作月饼的,我们是否可以在代码实现一个月饼售卖的架构设计和设计模式。
借此机会,我们用Lambda实现一遍月饼制作,下单,售卖的开发设计模式,主要有制作月饼的工厂模式、
一、使用工厂模式制作月饼
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思维方式。使用工厂模式,我们就无需向消费者们暴露,我们的月饼(实例化月饼对象)的制作逻辑,就能完成月饼的制作。
1、使用工厂创建月饼实例
我们需要一个月饼工厂(MoonCakeFactory)或者叫月饼小作坊,在工厂里我们可以创建一个map 将产品名映射到对应的构造函数中,提供一个像工厂模式一样,利用map来实例化不同对象。
/**
* 一个简单的月饼制作工厂
* @author XiaoMing
*/
public class MoonCakeFactory {
/**
* 我们可以创建一个map 将产品名映射到对应的构造函数中
*/
final static Map<String, Supplier<MoonCakeInfo>> map = new HashMap<>();
static {
// 五仁的,我的最爱
map.put("wuRen", WuRenMoonCakeInfo::new);
// 豆沙
map.put("redBeanPaste", RedBeanPasteMoonCakeInfo::new);
// 枣泥
map.put("jujubePaste", JujubePasteMoonCakeInfo::new);
// 蛋黄的
map.put("eggYolk", EggYolkMoonCakeInfo::new);
}
/**
* 像工厂模式一样,利用map来实例化不同对象
*
* @param moonCakeType 月饼类型
*/
public static MoonCakeInfo createMoonCake(String moonCakeType) {
// 获取月饼供应商
Supplier<MoonCakeInfo> moonCakeInfoSupplier = map.get(moonCakeType);
if (null != moonCakeInfoSupplier) {
return moonCakeInfoSupplier.get();
}
throw new IllegalArgumentException("No such MoonCakeInfo" + moonCakeType);
}
}
/**
* @author XiaoMing
*/
public class WuRenMoonCakeInfo extends MoonCakeInfo {
private String wuRen;
public String getWuRen() { return wuRen; }
public void setWuRen(String wuRen) { this.wuRen = wuRen; }
}
2、工厂模式剖析
现在我们就可以试着拿到对应的,实例化的月饼对象了
WuRenMoonCakeInfo wuRen = (WuRenMoonCakeInfo) createMoonCake("wuRen");
我们看完了这个例子,现在思考内部的问题,这么做有什么好处?为什么createMoonCake是一个static的方法?
我们制作月饼有很多馅,除了馅我们还可以取对应馅(moonCakeType)的时候,就可以获取到一个实例化的对象,不需要我们在使用的地方创建,将工厂定义为静态方法是一个常用技巧,称为静态工厂,不需要创建方法来实例化对象,将实例化对象和创建方法解耦。
总结一下,工厂模式是用一个专业类(工厂类)来负责一种产品的对象创建。这样做的好处是,1、把对象的创建和使用分开;2、将生产过程集中后,便于集中管理(增删改);3、当实体类有变动时,使用者不需要再去修改代码。
二、使用策略模式限制购买月饼类型
一个礼盒中有很多类型的月饼,有些馅并不我待见,博主曾经吃过一个咖啡馅月饼,这里面我们把奇奇怪怪的馅扣除去。校验是否为有效订单,设置该策略不允许咖啡馅月饼和榴莲馅的下单
1、实战代码
策略模式可以理解为一种通过算法解决一类问题的通用方案,策略模式包括该算法的接口,一个或多个接口的实现逻辑,以及策略对象,下面我们用lambda表达式实现,Validator 相当于一个中转站,strategy.validatorOrder(orderType);可以通过下属lambda实现,也可以通过实现类,继承Strategy 接口实现
/**
* 假设为下单主流程
* 我们主要关注 策略模式下订单类型的校验,这几个步骤
*/
public void submitOrder(OrderInfo orderInfo) {
// ...
// 校验是否为有效订单,设置该策略不允许咖啡馅月饼和榴莲馅的下单
Validator v1 = new Validator(orderType -> !orderType.equals("Coffee") || !orderType.equals("Durian"));
v1.validatorOrder(orderInfo.getOrderType());
// ...
}
/**
* @author XiaoMing
*/
public class Validator {
private Strategy strategy;
public Validator(Strategy strategy) {
this.strategy = strategy;
}
public boolean validatorOrder(String orderType) {
return strategy.validatorOrder(orderType);
}
}
/**
* @author XiaoMing
*/
public interface Strategy {
/**
* 函数式接口,通过调用 Validator时实现
*/
boolean validatorOrder(String orderType);
}
一般我们也可以使用实现类实现
/**
* @author xiaoming
* @date 2022/8/27-10:33
*/
public class RealOrderImpl implements Strategy {
@Override
public boolean validatorOrder(String orderType) {
System.out.println("real");
return orderType.equals("real");
}
}
public class O2OOrderImpl implements Strategy {
@Override
public boolean validatorOrder(String orderType) {
System.out.println("O2O");
return orderType.equals("O2O");
}
}
策略模式类图:
2、策略模式剖析
策略模式需要做的就是当请求进来时候,同一个入口让他根据这个人请求的行为去执行其中某一个类中的方法。
策略接口的定义,通常包含两个方法:获取策略类型的方法和处理策略业务逻辑的方法。策略接口的实现,每种支付类都实现了上述接口(基于接口而非实现编程),这样我们可以灵活的替换不同的支付方式(上文代码段就是使用lambda表达式实现的)。
接口只负责业务策略的定义,每个策略的具体实现单独放在实现Impl中,我们可以使用工厂类 Factory 只负责获取具体实现类,而具体调用代码则负责业务逻辑的编排。这些实现用到了面向接口而非实现编程,满足了职责单一、开闭原则,从而达到了功能上的高内聚低耦合、提高了可维护性、扩展性以及代码的可读性。
三、模板方法模式设计月饼的优惠决策
我们购买月饼在电商业务中有很多优惠信息,例如红包、平台券、商家券、满减、秒杀活动等等, 如果每个优惠写一个方法那么就不方便阅读和管理,我们可以用这种方式将代码扩展性做的很好假设为下单主流程,我们主要关注 优惠决策与核销->优惠信息落库,这几个步骤。
1、使用模板方法实现优惠活动
让我们从模板方法模式设计月饼的优惠决策的例子着手,看看这个模式是如何工作的。
/**
* 假设为下单主流程
* 我们主要关注 优惠决策与核销->优惠信息落库,这几个步骤
*/
public void submitOrder(List<OrderInfo> orderList) {
// ...
// 优惠决策与核销
writeOff(orderList, couponInfos -> {
// 将优惠信息落库
transaction(orderList);
});
// ...
}
/**
* 我们购买月饼在,电商业务中有很多优惠信息,例如红包、平台券、商家券、满减、秒杀活动等等
* 如果每个优惠写一个方法那么就不方便阅读和管理,我们可以用这种方式将代码扩展性做的很好
*/
public void writeOff(List<OrderInfo> orderList, Consumer<List<CouponInfo>> consumer) {
// 每个优惠信息,由自己的实现类实现
List<CouponInfo> couponInfos = consume(orderList);
// 此处将结果保存
consumer.accept(couponInfos);
}
/**
* 每个优惠信息自己实现 ServiceImpl
*/
private List<CouponInfo> consume(List<OrderInfo> orderList) {
List<CouponInfo> couponInfos = new ArrayList<>();
// 核销后返回信息(实现业务逻辑)
// ...
return couponInfos;
}
/**
* 将优惠信息落库
*/
private static void transaction(List<OrderInfo> orderInfos) {
}
2、模板方法剖析
模板方法模式,如果你需要采用某个算法的框架,同时又希望有一定的灵是活度,能对它的某些部分进行改进,那么采用模板方法设计模式是比较通用的方案。这样讲有些抽象。换句话说,模板方法模式在你希望使用这个算法,但是需要对其中的某些行进行改进,才能达到希望的效果时是非常有用的。
优点,1、提高代码复用性,可以将相同部分的代码放在抽象的父类中;2、提高了拓展性,将不同的代码放入不同的子类中,通过对子类的扩展增加新的行为;3、实现了反向控制,通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为。
缺点,1、引入了抽象类,每一个不同的实现都需要一个子类来实现,导致类的个数增加,从而增加了系统实现的复杂度。
场景,1、一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现;2、各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
来源:https://blog.csdn.net/FMC_WBL/article/details/126533844


猜你喜欢
- java 可变参数详解 可变参数(Varargs)使程序员可以声明一个接受可变数目参数的方法。可变参数也
- 本文实例讲述了C#在RichTextBox中显示不同颜色文字的方法。分享给大家供大家参考。具体实现方法如下:#region 日志记录、支持其
- 目录服务注册服务发现服务注册引入相关依赖:<?xml version="1.0" encoding="U
- 一.利用二进制状态法求排列组合,此种方法比较容易懂,但是运行效率不高,小数据排列组合可以使用import java.util.Arrays;
- springboot项目不配置数据源启动报错spring boot默认会加载org.springframework.boot.autocon
- 一、前言在C#中,由于有了垃圾回收机制的支持,对象的析构和以前的C++有了很大的不同,这就要求程序员在设计类型的时候,充分理解.NET的机制
- 目录Future -> 代表的是未来的一个凭据AsynFuture -> Future具体实现类FutureService -&
- 在android应用中,多屏滑动是一种很常见的风格,没有采用viewpager的代码实现会很长,如果采用ViewPager,代码就会短很多,
- 最近在做一个搜索相关的项目,需要爬取网络上的一些链接存储到索引库中,虽然有很多开源的强大的爬虫框架,但本着学习的态度,自己写了一个简单的网络
- Android中的消息处理机制大量依赖于Handler。每个Handler都有对应的Looper,用于不断地从对应的MessageQueue
- Author:jeffreyDate:2019-04-08一、开发环境:1、mysql - 5.72、navicat(mysql客户端管理工
- 使用Spring Boot 与Dubbo集成,这里我之前尝试了使用注解的方式,简单的使用注解注册服务其实是没有问题的,但是当你涉及到使用注解
- 前言分页是我们在开发中绕不过去的一个坎!当你的数据量大了的时候,一次性将所有数据查出来不现实,所以我们一般都是分页查询的,减轻服务端的压力,
- 文件上传下载前台:1. 提交方式:post2. 表单中有文件上传的表单项: <input type=”file” />3. 指定
- 之前知道spring支持JSR校验,在自己定义的bean中加入@NotNull,@NotBlank,@Length等之类的校验用于处理前台传
- 最近有朋友问屏幕锁定的问题,自己也在学习,网上找了下也没太详细的例子,看的资料书上也没有有关屏幕锁定程序的介绍,下个小决心,自己照着官方文档
- 刚刚学习Android,用Gallery作了一个小demo,用来记录一下。package com.example.galleryex02;i
- 做侧滑删除网上有很多方案,比如重写Listview实现滑动的监听,今天说下一个SwipeListView,这个是之前一个朋友在网上开源的一个
- 一、单例模式的思想想整理一些 java 并发相关的知识,不知道从哪开始,想起了单例模式中要考虑的线程安全,就从单例模式开始吧。以前写过单例模
- Spring Security中的内置过滤器顺序是怎么维护的?我想很多开发者都对这个问题感兴趣。本篇我和大家一起探讨下这个问题。HttpSe