面向对象程序设计设计模式论文姓名:邓鹏辉班级:软硕4班学号:M*********一.程序设计目标和使用说明该程序在eclipse3.2版本中完成,用的是jdk1.5。
该程序的设计目的是为了学习java设计模式,应用其中的少数几个模式编写一个程序,在编写程序的过程中亲身实践相应设计模式,学习体会。
该程序的设计目标是完成一个餐厅的经营流程。
其中的角色包括消费者,服务员,经理,以及厨房的厨师。
在程序设计中有四个包。
图1-1 项目包1.client包。
图1-2 Client包文件其中利用策略模式,对顾客进行划分。
让顾客具有各自不同的特点和属性,并且可以在程序运行的时候,利用相关方法进行修改,实现客户在进行时的需求更改。
2.waiter 包。
图1-3 waiter包文件在waiter包中,是利用观察者模式实现的餐厅服务系统。
经理作为subject,然后服务员作为Observer,订阅信息。
在信息改变的时候,由经理通知所有的服务员,以便所有的服务员得到最新的信息,在业务方面不会出错。
然后由于餐厅厨房里也需要知道菜单信息,以及及时更改的信息。
所以将chef也作为订阅者加入到list中,跟服务员一起接收新的信息。
3.kitchen包。
包括文件:图1-4 kitchen包文件利用模板模式将菜肴加工的过程进行优化,将相同步骤抽象出来。
然后又利用简单工厂模板方法来将菜类进行抽象,利用一个例子,将牛肉类进行抽象。
4.myrestaurant包。
其中包括main方法。
图1-5 myrestaurant包文件在该包中,main方法中导入前三个包,进行综合调用。
综合利用之前的各个角色,可以充分模拟餐厅的基本业务。
实例一个晚宴和午餐的客人。
他们是根据自己的特点来构造了自己的属性。
后来他们又更改了自己选择。
然后他们提交点单给经理,经理会同志所有服务员和厨师。
厨师会根据自己读到的点单来做菜。
二.模板及其描述本程序中综合运用了策略模式,观察者模式,模板模式和工厂模式。
下面就四个模式分别进行说明。
2.1策略模式策略模式(Strategy Pattern)中体现了两个非常基本的面向对象设计的基本原则:封装变化的概念;编程中使用接口,而不是对接口实现。
策略模式属于对象行为型设计模式,主要是定义一系列的算法,把这些算法一个个封装成拥有共同接口的单独的类,并且使它们之间可以互换。
策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。
这里的算法不要狭义的理解为数据结构中算法,应该理解为不同的业务处理方法。
这种做法会带来什么样的好处呢?它将算法的使用和算法本身分离,即将变化的具体算法封装了起来,降低了代码的耦合度,系统业务策略的更变仅需少量修改。
算法被提取出来,这样可以使算法得到重用,这种情况还可以考虑使用享元模式来共享算法对象,来减少系统开销(但要注意使用享元模式的建议条件)。
先看看策略模式的结构:要使算法拥有共同的接口,就要实现一个接口或者一个抽象类出来才行。
这样结构的轮廓也就出来了,可用简单的类图来表示它们之间的关系:图2-1 策略模式类图策略模式由三个角色组成:算法使用环境角色:算法被引用到这里和一些其它的与环境有关的操作一起来完成任务;抽象策略角色:规定了所有具体策略角色所需的接口。
在java它通常由接口或者抽象类来实现;具体策略角色:实现了抽象策略角色定义的接口。
图2-2 Client包文件在此包中,CookingOrder,SweetOrder,DrinkOrder为三个接口,分别用来定义顾客的三个餐饮属性。
FiveCooking,SevenCooking,TatalCooking为对接口CookingOrder 的实现。
SweetOk,SweetNo为对SweetOrder的实现。
DrinkTea,DrinkCoffee,DrinkUsquebaugh为对接口DrinkOrder的实现。
分别完成对菜式的要求,甜点的要求,和酒水的要求。
接口只提供空方法,后面继承类个别实现。
举一例:a)接口SweetOrderpackage client;public interface SweetOrder {public String sweet();}提供一个抽象方法。
b)类SweetOkpackage client;public class SweetOk implements SweetOrder {public String sweet() {System.out.println("I want the Sweet");return"I want the Sweet";}}c)类SweetNo:package client;public class SweetNo implements SweetOrder {public String sweet() {System.out.println("I do not want the Sweet");return"I do not want the Sweet";}}而客人类client则面向接口编程,并使整个客人类中的属性可以利用接口和其方法实现自选和变更。
public abstract class Clients {CookingOrder cookingOrder;SweetOrder sweetOrder;DrinkOrder drinkOrder;//面向接口编程public Clients(){}public void setCookingOrder (CookingOrder cook) {cookingOrder = cook;}//动态设置点餐要求面向接口编程,即利用接口将不同的接口实现包括进去,实现多项选择,策略变化。
而DinnerClient则是一个具体的客人类,根据晚宴的要求,针对自己实现有特点的选择。
2.2观察者模式在设计一组依赖的对象与它们所依赖的对象之间一致(同步)的交流模型时,观察者模式(Observer Pattern)很有用。
它可以使依赖对象的状态与它们所依赖的对象的状态保持同步。
这组依赖的对象指的是观察者(Observer),它们所依赖的对象称为主题(Subject)。
为了实现观察者(Observer)的状态与主题(Subject)保持同步,观察者模式(Observer Pattern)定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
由于给定主体的观察者链表需要动态的变化,因此一个主题不能维护一个静态的观察者链表。
因此关注于主题状态的任何对象都需要明确地注册自己为主体的一个观察者。
主题状态发生的变化,都需要通知所有的以注册的观察者。
从主题接到通知以后,每一个观察者查询主题,使自己的状态与主题的同步。
因此一个主题扮演着发布者的角色,发布信息到所有的以订阅的观察者。
换句话说,主题和它的观察者之间包含了一对多的关系。
当主题的实例的状态发生变化时,所有的依赖于它的观察者都会得到通知并更新自己。
每一个观察者对象需要向主题注册,当主题的状态发生变化的时候得到通知。
一个观察者可以注册或者订阅多个主题。
当观察者不希望再得到通知时,它可以向主题进行注销。
本模式的类图结构如下:图2-3 观察者模式的静态结构在观察者模式里有如下的角色:抽象主题(Subject)角色:主题角色把所有的观察者对象的引用保存在一个列表里;每个主题都可以有任何数量的观察者。
主题提供一个接口可以加上或撤销观察者对象;主题角色又叫做抽象被观察者(Observable)角色;图2-4 抽象主题角色抽象主题角色,有时又叫做抽象被观察者角色,可以用一个抽象类或者一个接口实现;在具体的情况下也不排除使用具体类实现。
抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到通知时更新自己;图2-5 抽象观察角色抽象观察者角色,可以用一个抽象类或者一个接口实现;在具体的情况下也不排除使用具体类实现。
具体主题(ConcreteSubject)角色:保存对具体观察者对象有用的内部状态;在这种内部状态改变时给其观察者发出一个通知;具体主题角色又叫作具体被观察者角色;图2-6 具体主题角色具体主题角色,通常用一个具体子类实现。
具体观察者(ConcreteObserver)角色:保存一个指向具体主题对象的引用;和一个与主题的状态相符的状态。
具体观察者角色实现抽象观察者角色所要求的更新自己的接口,以便使本身的状态与主题的状态自恰。
图2-7具体观察者角色具体观察者角色,通常用一个具体子类实现。
观察者模式的效果:观察者模式的效果有以下的优点:第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。
被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。
被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。
由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。
第二、观察者模式支持广播通讯。
被观察者会向所有的登记过的观察者发出通知。
观察者模式有下面的缺点:第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。
在使用观察者模式是要特别注意这一点。
第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。
在本设计中,经理需要接受点单,然后通知所有的服务员以及做菜的师傅。
由于点单要及时也要高效经济,所以特别适用观察者模式。
经理为Subjectpublic interface ManagerSubject {public void registerObserver (WaiterObserver o);public void removeObserver (WaiterObserver o);public void notifyObservers ( );}//接口声明。
以下为经理的具体类。
import java.util.*;public class Manager implements ManagerSubject {private ArrayList waiterObservers;//储存订阅者,及保存餐厅所有服务员,以及后面厨房的厨师private String newOrder;//保存定单public void Manager(){waiterObservers = new ArrayList();}//通知所有的订阅者,及及时将新的定单或修改的定单通知给所有的服务员,以及后面厨房的厨师public void notifyObservers() {// TODO Auto-generated method stubfor (int i = 0; i < waiterObservers.size(); i++) {WaiterObserver observer = (WaiterObserver)waiterObservers.get(i);observer.update(newOrder);}}//注册订阅者,及给餐厅增加服务员,以及后面厨房的厨师public void registerObserver(WaiterObserver o) {// TODO Auto-generated method stubwaiterObservers.add(o);}//移除订阅者,开除服务员,以及后面厨房的厨师public void removeObserver(WaiterObserver o) {// TODO Auto-generated method stubint i = waiterObservers.indexOf(o);if (i >= 0)waiterObservers.remove(i);}//在此时调用通知方法public void orderChanged() {notifyObservers();}//接收新的定单然后通知所有服务员,以及后面厨房的厨师public void setMeasurements(String order) {this.newOrder = order;orderChanged();}}注释比较清楚,注册,注销函数。