Java设计模式实现烹饪助手程序

Java设计模式实现烹饪助手程序


一. 程序设计目标和使用说明

1、程序设计目标

    该程序在eclipse4.6.3版本中完成,用的是jdk1.7。
    该程序的设计目的是为了学习java设计模式,应用其中的几个模式编写一个程序,在编写程序的过程中亲身实践相应设计模式,学习体会。
    该程序的设计目标是完成一个采购食材的基本流程。程序根据用户选择的菜单,给出需要购买的食材,并计算费用,用户付款后,通知超市工作人员接单,用户只需取货即可,使食材推荐、采购、付款一键完成,为用户节省了大量时间。
    该程序的角色包括用户、超市经理和超市工作人员。程序用到了抽象工厂模式、装饰器模式、策略模式和观察者模式。

2、使用说明

①界面展示

    如图1所示,程序界面包括六个部分:
这里写图片描述

1、 最上面是收费策略提示区,展示了优惠信息。
2、 菜单选择板,包含用户可选菜单,可选择多个菜单。
3、 已选菜品展示板,根据用户选择的菜单,展示需要购买的食材和价格。
4、 折扣展示板,展示用户享受的折扣、总额、打折后的实付金额。

如图2所示,当订单金额不满50元时,显示无折扣。
这里写图片描述

如图3所示,当订单金额满足折扣条件时,会显示相应的折扣。
这里写图片描述
5、 下单按钮,用户点击下单。
6、 订单信息,当用户点击下单按钮后,展示订单信息。
如图4所示,用户点击下单,会在订单按钮下方展示当前订单信息。
这里写图片描述

②程序展示

    如图5所示,在程序设计中有五个包。
这里写图片描述
1.cookHelper包。如图6所示,CookHelper.java中包含main方法:
这里写图片描述
在该包中导入前三个包,进行综合调用,实现该程序的各项功能。

2.drinkType 包。如图7所示,中间文件包括:
这里写图片描述

    在drinkType包中,利用装饰器模式,为用户订单添加饮料,动态地扩展现有菜单内容,其中ChooseDrink是一个作为装饰类的抽象类,Cola、Juice和MilkTea是实现了该接口的具体类,当商家需要添加饮料的种类时,直接添加一个实现ChooseDrink接口的具体类,然后在相应的方法中调用即可。

3.foodType 包。如图8所示,中间文件包括:
这里写图片描述
    利用抽象工厂模式将菜品的创建过程进行优化,建立多个工厂类,其中Food是一个抽象工厂,ChineseFoodA、ChineseFoodB、ThaiFoodA、ThaiFoodB是该工厂的实现类,CookFood提供了调用工厂类的接口,CookChineseFoodA、CookChineseFoodB、CookThaiFoodA、CookThaiFoodB是该接口的具体实现。如果需要增加菜单,可通过添加新的工厂类实现。

4.payMoney包,如图9所示,中间文件包括:
这里写图片描述

    利用策略模式,对折扣类别进行划分。并且在程序运行的时候,调用相关方法,使用相关算法进行计算,得出用户实付金额。其中Context是策略模式的抽象类,提供折扣的接口,DiscountA、DiscountB、DiscountC是折扣的具体类,定义了不同的折扣类型。当商家需要添加新的折扣时,直接添加一个新的类,并实现Context接口即可。

5.superMarket包,如图10所示,中间文件包括:
这里写图片描述
    在superMarket包中,是利用观察者模式实现超市的订单管理。经理作为subject,超市工作人员作为Observer,订阅信息。在上述文件中,ManagerSubject为经理的抽象类,是抽象主题角色,Manager表示具体的经理,即被观察者;WorkerObserve表示观察者抽象类,是抽象观察者对象,WorkerA、WorkerB、WorkerC表示超市工作人员,即观察者。在信息改变的时候,由经理通知所有的超市工作人员,以便所有的超市工作人员得到最新的信息,在业务方面不会出错。

二. 模板及其描述

    本程序中综合运用了抽象工厂模式,装饰器模式,策略模式和观察者模式。下面就四个模式分别进行说明。

① 抽象工厂模式(Abstract Factory):

    工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
    普通工厂模式存在一个问题就是,类的创建依赖工厂,如果想扩展程序,必须对工厂类进行修改,违背了闭包原则。而抽象工厂模式可以很好地解决这一问题。
    抽象工厂模式创建多个工厂类,当需要增加新功能时,直接增加新的工厂类即可,不需要修改之前的代码。
    如图11所示,例如发送邮件和发送消息时,有一个邮件工厂和消息工厂,用于提供邮件和消息,同时提供了一个发送的接口,由发送邮件和发送消息的类来实现该接口展示了抽象工厂模式各部分以及它们之间的关系,参照该示例,我们可以用于设计本次菜单的创建工作:
这里写图片描述

    在此程序中,对菜单运用了抽象工厂模式。
    具体的菜品为一个实现类:

    public interface Food {public String cook();
}

    在实现类中,拥有一个共同的方法,即烹饪cook()。

    后面有四种不同的菜分别实现此接口,并返回对应菜品需要购买的食材和单价,其中一个实现类如下所示:

    public class ChineseFoodA implements Food{@Overridepublic String cook() {return "青椒5元+猪肉15元";}
}

    烹饪菜品为一个工厂类,提供一个烹饪的实际操作接口,并返回一个菜品类型:

public interface CookFood {public Food cookFood();
}

    工厂类的实现类有四个,实现了烹饪食材的接口,并返回对应的菜品。其中一个如下所示:

public class CookChineseFoodA implements CookFood{public Food cookFood() {return new ChineseFoodA();}
}

    抽象工厂模式很好地实现了面向接口编程,菜单作为一个工厂,当需要在菜单中添加新的菜品时,直接添加一个工厂类和一个实现类即可。

② 装饰器模式(Decorator):

    装饰模式能够实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。它基于对象组合的方式,可以很灵活的给对象添加所需要的功能。装饰器模式的本质就是动态组合。动态是手段,组合才是目的。
    装饰模式是通过把复杂的功能简单化,分散化,然后再运行期间,根据需要来动态组合的这样一个模式。
    如图12所示,展示了抽象工厂模式各部分以及它们之间的关系,其中Source类是被装饰类,Decorator类是一个装饰类,可以为Source类动态的添加一些功能:
这里写图片描述

    在此程序中,对饮料运用了装饰器模式。

    在本程序中,用户选择的菜品Food是被装饰类,而在drinkType包中的ChooseDrink是一个作为装饰类的抽象类,实现了被装饰类的方法,如下所示:

    public abstract class ChooseDrink implements Food{public String cook(){return null;}
}

    后面有三种不同的饮料分别实现此接口,并返回对应饮料需要购买的单价,其中一个实现类如下所示:

    public class Cola extends ChooseDrink{public String cook(){return "可乐5元      ";}
}

    装饰器模式使得用户可以动态地在菜单中添加或删除饮料,当需要添加新品种的饮料是,直接添加一个装饰类的实现类即可。

③ 策略模式(Strategy Pattern):

    策略模式中体现了两个非常基本的面向对象设计的原则:1、封装变化的概念;2、编程中使用接口,而不是对接口实现。
    策略模式属于对象行为型设计模式,主要是定义一系列的算法,把这些算法一个个封装成拥有共同接口的单独的类,并且使它们之间可以互换。策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。
    策略模式带来的好处是,它将算法的使用和算法本身分离,即将变化的具体算法封装了起来,降低了代码的耦合度,系统业务策略的更变仅需少量修改。
    如图13所示,为策略模式的结构,要使算法拥有共同的接口,就要实现一个接口或者一个抽象类出来才行。这样结构的轮廓也就出来了,可用简单的类图来表示它们之间的关系:
这里写图片描述
策略模式由三个角色组成:
1) 算法使用环境角色:算法被引用到这里和一些其它的与环境有关的操作一起来完成任务;
2) 抽象策略角色:规定了所有具体策略角色所需的接口。在java它通常由接口或者抽象类来实现;
3) 具体策略角色:实现了抽象策略角色定义的接口。

在此程序中,对折扣的计算运用了策略模式。

其中,算法使用环境角色为包含main方法的CookHelper,其中使用策略模式的代码如下所示:

    Context context;
if (totalMoney >= 50 && totalMoney < 100) {context = new Context(new DiscountA());t2.setText(context.sale()+"\n总额:"+totalMoney+"元\n实付:"+(totalMoney-5)+"元");
} else if (totalMoney >= 100) {context = new Context(new DiscountB());t2.setText(context.sale()+"\n总额:"+totalMoney+"元\n实付:"+(totalMoney-15)+"元");
} else {t2.setText("无折扣\n总额:"+totalMoney+"元\n实付:"+totalMoney+"元");
}

    在Discount接口中定义了抽象角色,其中定义了一个sale方法,返回一个字符串类型,当用户选好菜单后,该方法根据总价格计算用户享受的折扣,并计算用户的实付金额,代码如下所示:

public interface Discount {public String sale();
}

    在代码中,具体策略角色有三个,分别实现了抽象策略角色的接口,表示不同种类的折扣。当超市需要添加新的折扣策略时,直接添加具体策略角色类,并实现抽象角色类的接口即可,其中一个具体角色类的代码如下所示:

    public class DiscountA implements Discount{@Overridepublic String sale() {return "满50减5";}
}
④ 观察者模式(Observer Pattern):

    观察者模式处理的是类与类之间的关系,不涉及到继承,它的工作过程是,当一个对象变化时,其它依赖该对象的对象都会收到通知,并随着变化,作出相应的反应。因此,在设计一组依赖的对象与它们所依赖的对象之间一致(同步)的交流模型时,观察者模式很有用。它可以使依赖对象的状态与它们所依赖的对象的状态保持同步。这组依赖的对象指的是观察者(Observer),它们所依赖的对象 称为主题(Subject)。为了实现观察者(Observer)的状态与主题(Subject)保持同步,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
    由于给定主题的观察者链表需要动态的变化,因此一个主题不能维护一个静态的观察者链表。因此关注于主题状态的任何对象都需要明确地注册自己为主体的一个观察者。主题状态发生的变化,都需要通知所有的以注册的观察者。从主题接到通知以后,每一个观察者查询主题,使自己的状态与主题的同步。因此一个主题扮演着 发布者的角色,发布信息到所有的以订阅的观察者。
    因此,主题和它的观察者之间包含了一对多的关系。当主题的实例的状态发生变化时,所有的依赖于它的观察者都会得到通知并更新自己。每一个观察者对象需要向主题注册,当主题的状态发生变化的时候得到通知。一个观察者可以注册或者订 阅多个主题。
    在观察者模式里有如下的角色:
    1) 抽象主题角色:抽象主题角色定义了一个接口,把所有的观察者对象的引用保存在一个列表里,每个主题都可以有任何数量的观察者。主题提供一个接口可以加上或者撤销观察者。
    2) 抽象观察者角色:抽象观察者角色为所有的具体观察者定义一个接口,在得到通知时更新自己。
    3) 具体主题角色:又称为具体被观察者角色,保存对具体观察者对象有用的内部状态;在这种内部状态改变时给其观察者发出一个通知。
    4) 具体观察者角色:保存一个指向具体主题对象的引用;和一个与主题的状态相符的状态。具体观察者角色实现抽象观察者角色所要求的更新自己的接口,以便使本身的状态与主题的状态自恰。
    如图14所示为观察者模式的类图结构,MySubject类就是我们的主对象,即具体的主题角色,Observer1和Observer2是依赖于MySubject的对象,用于观察MySubject的动态,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类为抽象主题角色,定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象:
这里写图片描述

    在此程序中,对超市运用了观察者模式。

    在本设计中,超市经理需要接受订单,然后通知所有超市工作人员,使超市工作人员配齐用户用户的订单,该工作方式很适合使用观察者模式。

    如图15所示为本设计中实现观察者模式的各个接口和类,

这里写图片描述
    其中ManagerSubject为经理的抽象类,是抽象主题对象,在该接口中定义着一些方法,可用于添加或删除观察者,通知观察者以及一些自身的操作,代码部分如下所示:

    public interface ManagerSubject {/*增加观察者*/  public void add(WorkerObserver workerObserver);  /*删除观察者*/  public void del(WorkerObserver workerObserver);       /*通知所有的观察者*/  public List<String> notifyObservers();       /*自身的操作*/  public void operation();  
}

    Manager类表示经理,是抽象主题对象ManagerSubject的具体实现,在该类中,定义了监控对象的列表,实现了ManagerSubject类中增加观察者、删除观察者、通知所有观察者的具体方法,以及一些自身的操作。代码部分如下所示:

    public class Manager implements ManagerSubject{private Vector<WorkerObserver> vector = new Vector<WorkerObserver>();@Overridepublic void add(WorkerObserver workerObserver) {// TODO Auto-generated method stubvector.add(workerObserver);}@Overridepublic void del(WorkerObserver workerObserver) {// TODO Auto-generated method stubvector.remove(workerObserver);}@Overridepublic List<String> notifyObservers() {// TODO Auto-generated method stubList<String> aList = new ArrayList<String>();Enumeration<WorkerObserver> enumo = vector.elements();  while(enumo.hasMoreElements()){  aList.add(enumo.nextElement().update(""));  }return aList;}@Overridepublic void operation() {// TODO Auto-generated method stub}
}

    WorkerObserver为工作人员的抽象类,是抽象观察者角色,它为所有的具体观察者定义一个接口,在得到通知时更新自己,代码部分如下所示:

    public interface WorkerObserver {public String update(String newOrder);
}

    WorkerA和WorkerB表示工作人员,它实现类抽象观察者角色中的update方法,该方法接收一个字符串,表示订单的具体信息,在方法结束时返回一个字符串,表示该工作人员已经接收到了该订单。其中WorkerA的代码部分如下所示:

    public class WorkerA implements WorkerObserver{@Overridepublic String update(String newOrder) {// TODO Auto-generated method stubreturn "工作人员A收到订单" + newOrder;}
}

    以上及为本程序中具体运用的四个模式的说明,有对模式的理论说明还有针对本程序的实际讲解。由于篇幅所限制,不便把所有的代码贴上,具体请参看程序代码。

三. 总结

    首先,设计模式是建立在某一门语言的基础之上的,设计模式是程序大牛对编程方式的总结,所以,要想很好地使用设计模式,必须要能十分熟练地使用这门语言进行编程。在本次设计中,我使用的是基于java语言的设计模式,java是一门面向对象的语言,能灵活的运用抽象类,接口,抽象方法,静态方法等等,所以,要想用好设计模式,必须首先对java语言的使用有一个深入的了解,并且十分熟练。因此,学习设计模式需要扎实的语言功底。
    在初学设计模式并尝试编写代码时,我觉得很疑惑,因为很多时候一个类和几个方法就可以解决的问题,我们为什么要编写接口和多个类,这样是否提高了程序的复杂性,使得我们所写的程序不易于理解?但是,当多次使用设计模式,将多个设计模式用到一个项目中,并且项目达到一定规模时,我理解了设计模式给我们带来的极大便利之处。使用设计模式,我们就可以在自己进行程序设计、类的编写时可以去复用程序大牛所设定的设计模式,为解决自己的问题找到更好的方法避免走弯路,直接利用大牛的设计模式可以节省设计解决方案的时间,GOF提出的23种设计模式涉及的范围很广,很多时候我们都可以直接找到一个适合的设计模式。
    当然,我们学设计模式,是为了学习如何合理的组织我们的代码,如何解耦,如何真正的达到对修改封闭对扩展开放的效果,而不是去背诵那些类的继承模式,不能一味复用,而牺牲了代码的性能,应该根据实际情况,总结出一个对自己的程序最有效的方法。
    只有掌握住设计模式的核心思想,才能正确、灵活的应用设计模式,否则再怎么使用设计模式,也不过是生搬硬套。总之,学习设计模式对于一个面向对象的程序设计人员来说是十分必要的,而且在学习的过程中我们也能发现很多编程的乐趣。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/28178.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博士毕业,高校青椒还是30万年薪私企?

来源 | 知乎 网址 | https://www.zhihu.com/question/58594731 编辑 | 深度学习与计算机视觉 声明&#xff1a;仅做学术分享&#xff0c;侵删 年龄不占优势&#xff0c;高校稳定&#xff0c;企业收入高&#xff0c;如何选择&#xff1f; 作者&#xff1a;光子https://www.zhihu…

java设计模式-迭代器模式

java设计模式-迭代器模式 一、了解迭代器模式 1.1 什么是迭代器模式 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素&#xff0c;而又不暴露其内部的表示。 迭代器模式把游走的任务放在迭代器上&#xff0c;而不是聚合上。这样简化了聚合的接口和实现&#xff0c;也…

3D设计云桌面

青椒云3D设计桌面云方案,为使用GPU高负载应用的设计师们提供强大支持,如3D建模、光线追踪、渲染计算等领域,带来极致流畅的3D设计桌面体验,同时提升工作效率、可管理性和安全性。3D设计桌面云方案满足了工业客户在专业设计场景中的以下需求 1、强大的图形计算引擎保证专业…

设计模式-建造者模式

设计模式-建造者模式 传统模式类JDK8的Builder 别名&#xff1a;创建者模式 建造者模式针对复杂对象&#xff0c;分离它们的构建与表示&#xff0c;达到同样构建过程创建不同表示的目的。 建造者模式封装了复杂对象的构建过程&#xff0c;通过子类继承或者重载的方式&#xff0…

设计模式---工厂模式

工厂模式 具体的需求 看一个披萨的项目&#xff1a;要便于披萨种类的扩展&#xff0c;要便于维护 披萨的种类很多&#xff08;比如 GreekPizz、CheesePizz 等&#xff09; 披萨的制作有 prepare、bake、cut、box 完成披萨店订购功能 public abstract class Pizza {protect…

浅谈设计模式

状态模式 核心思想就是用于解决一个物体在不同状态下复杂的逻辑行为&#xff0c;比如一个英雄有待机状态&#xff0c;行走状态&#xff0c;攻击状态&#xff0c;以后可能还会添加眩晕状态&#xff0c;冰冻状态一系列状态。 如果使用平常代码来写的话&#xff0c;就会使用分支语…

青椒开计算机课,不断学习 砥砺前行——揭开青椒成长的秘密

从上海到梧州&#xff0c;1700多公里&#xff1b;从2017年9月到今天&#xff0c;300多个日子。我们在互联网结缘&#xff0c;我们在互加遇见。于是&#xff0c;便开始了一路美丽的相伴&#xff0c;相伴在“互加”&#xff0c;相伴在“青椒”&#xff0c;相伴在“美丽乡村”………

了解计算机软件系统教学设计,认识计算机》教学设计

认识计算机》教学设计 作为一名教职工&#xff0c;就有可能用到教学设计&#xff0c;教学设计一般包括教学目标、教学重难点、教学方法、教学步骤与时间分配等环节。那么什么样的教学设计才是好的呢&#xff1f;以下是小编整理的认识计算机》教学设计&#xff0c;仅供参考&…

Java 设计模式——组合模式

概述 有时我们可能会被要求处理一个层级结构明显的对象&#xff0c;比如上下级的公司员工、比如层级嵌套的文件夹&#xff0c;还有丰富多彩的美食菜单。可是&#xff0c;我们可能要屡试不爽地编写深度搜索代码、要小心翼翼地编写递归逻辑。现在你可以忘掉这些&#xff0c;学习…

设计模式之模板方法模式

概述 在面向对象程序设计过程中&#xff0c;程序员常常会遇到这种情况&#xff1a;设计一个系统时知道了算法所需的关键步骤&#xff0c;而且确定了这些步骤的执行顺序&#xff0c;但某些步骤的具体实现还未知&#xff0c;或者说某些步骤的实现与具体的环境相关。 例如&#…

matlab 滤波器设计工具,滤波器设计工具快速入门

滤波器设计工具快速入门 要打开滤波器设计工具,请键入 filterDesigner(在 MATLAB 命令提示符下键入。) 将打开滤波器设计工具并显示“设计滤波器”面板。 请注意,当您打开设计滤波器并未启用。您必须对默认滤波器设计进行更改以启用设计滤波器。每次您要更改滤波器设计时,均…

ChatGPT有用到知识图谱吗?| 文末送最新《知识图谱实战》书籍

文末留言点赞前五名送书&#xff0c;截止时间2023.4.2(本周日) 20:00 进NLP群—>加入NLP交流群(备注nips/emnlp/nlpcc进入对应投稿群) 从搜索引擎到个人助手&#xff0c;我们每天都在使用问答系统。问答系统必须能够访问相关的知识并进行推理。通常&#xff0c;知识可以隐式…

ChatGPT的诞生

这就是为什么ChatGPT 不可能在中国出现的原因 自欺欺人在家里玩可以&#xff0c;但是 你只是这世界的1/6而已&#xff0c;不可能 欺骗其他5/6的人类 最后还是自己傻比了

51 种 AI 工具,生活、编程、内容创建都应该使用它

AI 正在席卷全球 &#x1f525;&#x1f525;&#x1f525; 它具有无限的潜力&#xff0c;并将改变我们的生活&#xff0c;让生活变得更美好。这项技术将迅速改进&#xff0c;您今天可以使用许多工具来提高您的工作效率&#xff0c;帮助您完成工作&#xff0c;为您提供有关许多…

SpringBoot+Vue+Uniapp搭建的Java版本的ChatGPT智能Ai对话系统

chatgpt-java-system 介绍 SpringBootVueUniapp搭建的Java版本的ChatGPT智能Ai对话系统&#xff0c;小程序和H5包含智能Ai对话、精美Ai壁纸、知识付费商城、积分、会员、分享等公功能&#xff1b;后端管理包括系统管理、智能对话、基本设置、系统监控、代码生成、壁纸管理和商…

chatgpt赋能python:Python解决找零问题--极简演示

Python解决找零问题 – 极简演示 在日常生活中&#xff0c;我们经常需要进行找零计算。如果使用笔和纸来手动计算&#xff0c;则会浪费很多时间和精力。但是Python作为一种高级编程语言&#xff0c;可以轻松地解决这个问题&#xff0c;省去人工计算的烦恼。 什么是Python找零…

九龙证券|远离资本市场噪音的四种方法

我们都知道人是自我完成的群体&#xff0c;自我完成便是便是有方案有目的辅导自己的行为&#xff0c;目标或预期在很大程度上决定着人们的取得感&#xff0c;就好像以下公式所表现的相同&#xff1a;取得感所得/预期&#xff0c;那么股市中的预期是什么&#xff1f;怎么进行预期…

Redis漏洞导致ChatGPT重大故障,OpenAI公布技术细节

因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享 点击关注#互联网架构师公众号&#xff0c;领取架构师全套资料 都在这里 0、2T架构师学习资料干货分 上一篇&#xff1a;ChatGPT研究框架&#xff08;80页PPT&#xff0c;附下载&#xff09;…

ChatGPT4 给出数据库开发者最容易犯的10个错误和解决方案

昨天 ChatGPT4 刚刚发布&#xff0c;迫不及待体验了一把。 ChatGPT 4 目前是付费使用&#xff0c;使用次数也有限制&#xff0c;门槛更高&#xff0c;API 调用费用是ChatGPT 3.5 的15倍&#xff0c;官网网站也经常登录不上。 我让 ChatGPT4 列举出【数据库开发者最容易犯的10个…

小白学习chatgpt

很明显&#xff0c;chatgpt的能力超出了人们过往对人工智能的认知&#xff0c;在使用过程中他的能力让我吃惊&#xff0c;而且具有通用性&#xff08;AGI&#xff09;&#xff0c;这一点在以往的人工智能中表现得比较少&#xff0c;具体在GPT-4的早期实验报告中有更多的说明。可…