软件设计模式sdp-第4章_第1页
软件设计模式sdp-第4章_第2页
软件设计模式sdp-第4章_第3页
软件设计模式sdp-第4章_第4页
软件设计模式sdp-第4章_第5页
已阅读5页,还剩64页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、软件设计模式第4章 GoF创建型模式结构型(Creational)模式GoF创建型模式的意图是解决对象创建的一类设计问题比如,需要保证某个类型的对象在运行时只有一个实例,并共享给所有使用该对象的客户端将一类对象的创建行为复用保证产品簇不同类型产品对象的创建一致性等提纲单例模式原型模式模式构造器模式抽象工厂模式工厂方法模式单例(Singleton)模式单例(Singleton)是指目标类(Class)只有一个实例对象(Object),并且向使用该对象的客户端提供访问单例的全局方法使用单例模式的场景有当一个类只能有一个实例,并且客户端需要访问该实例当一个类的实例化代价很大,且向所有客户端提供无状态

2、的服务(实例状态在程序中通常使用变量或域表达)或不因客户端变化而改变实例状态的服务单例类结构使用单例的练习COS系统的配置信息使用XML格式文件保存,COS启动后,需要向所有客户端(Client)程序共享该配置信息,并提供配置信息访问的接口需要单独设计一个配置信息类,负责封装配置信息,并向客户端提供服务配置信息类初始化时,需要将配置信息从XML数据源文件中读取并解析,这属于耗时操作;多次初始化会降低程序性能Configuration单例类图 public class Configuration /cosConfig是静态域,在Configuration类首次加载时初始化private stat

3、ic Configuration cosConfig=createInstance();private Configuration()/私有构造方法/* * 创建和初始化Configuration对象 */private static Configuration createInstance()Configuration c=new Configuration();/解析XML数据源,初始化creturn c;/* * 向客户端提供访问c的公共方法 */public static Configuration getInstance()return cosConfig; /* * 向客户端提供配

4、置信息访问的接口 */ public Result service(Parameter p) /服务实现 /return语句 使用单例时,需要注意以下问题编程语言中反射和序列化/反序列化可能会破坏单例特性多客户端并发访问单例时,也可能会破坏单例特性在软件系统中使用过多的单例对象,会导致使程序性能下降设计单例类时,并不一定要完全遵守GoF理论形式使用单例模式的行业案例1JDK的Runtime单例类JDK中的java.lang.Runtime即是一个标准的单例类java.lang.Runtime定义了许多实例方法,通过对象调用向客户端提供接口每一个Java应用都有唯一一个Runtime实例,用来与

5、应用的运行时环境交互 public class Runtime /静态私有域 private static Runtime currentRuntime = new Runtime();/* * 全局静态访问方法 */ public static Runtime getRuntime() return currentRuntime; /* * 私有无参构造方法 */private Runtime() /其他代码 使用单例模式的行业案例2Hibernate框架SessionFactory对象的单例构造程序员一般在使用Java ORM框架Hibernate时,会将org.hibernate.Ses

6、sionFactory的实例在自己的应用中构造为单例org.hibernate.SessionFactory的单例向所有客户端程序共享持久化存储的配置信息和其他 public class HibernateUtil /静态私有域private static final SessionFactory sessionFactory = buildSessionFactory();/* * 实例构造方法 */private static SessionFactory buildSessionFactory() try / 通过xml配置构建SessionFactory实例 return new Co

7、nfiguration().configure().buildSessionFactory( new StandardServiceRegistryBuilder().build() ); catch (Throwable ex) /异常处理 /* * 全局静态访问方法 */ public static SessionFactory getSessionFactory() return sessionFactory; 原型(Prototype)模式原型(Prototype)是指通过复制自己达到构造目标对象新实例的对象使用原型设计模式的场景有当一个类的实例状态只能是不同组合中的一种时,而不想通过

8、平行类或子类的方式区分不同的状态组合当业务代码中不能静态引用目标类的构造器来创建新的目标类的实例当目标类实例化代价昂贵,不同的客户端需要单独使用一个目标类的对象时原型模式类结构使用原型的练习COS的通知子系统负责发送多种类型的通知,如,订单通知、系统通知、会员通知等。不同种类通知,会有不同的标题、内容和尾注。同一种类的通知,又有不同的子类型通知,子类型通知标题、内容等不同,尾注、背景等相同;如,订单通知分成不同订单状态(订单已生成,订单已支付等)的子类型通知,系统通知分成不同消息级别(紧急,普通等)的子类型通知。如果为每个的通知类型或子类型单独设计一个类或子类,设计类的数量将会急剧增加原型No

9、tification的类结构public class Notification implements Cloneable private String title;/ 通知标题private String content;/通知内容private NotificationFooter footer;/通知尾注 /* * setters,getters方法省略 */Notification(NotificationFooter foo) footer = foo;/* * 克隆Notification对象(浅拷贝-shallow copy,共享footer) */Overridepublic N

10、otification clone() try return (Notification) super.clone(); catch (CloneNotSupportedException e) /异常处理e.printStackTrace();return null;public class NotificationProtoManager private static HashMap manager = new HashMap();/原型管理器static / 初始化订单通知的尾注对象NotificationFooter orderFooter = new NotificationFoot

11、er();/订单通知原型构造manager.put(order, new Notification(orderFooter);/其他原型构造 /* * 根据通知类型获取原型对象 */public static Notification getNotificationProto(String type) return manager.get(type); public class NotificationSender / 存储通知的发送队列 private Queue sendQueue = new LinkedBlockingQueue ();/* * 通过通知原型对象复制,完成新通知对象创建

12、 */public void sendNotification(String title, String content , Employee receiver, String type) Notification notification = NotificationProtoManager.getNotificationProto.clone();/生成新通知对象notification.setContent(content);/设置通知内容notification.setTitle(title);/设置通知标题 notification.setReceiver(receiver);/设置

13、通知接收者 send(notification); /发送通知/* * 发送通知 */private void send(Notification noti) sendQueue.add(noti);/其他操作使用原型模式时需要注意的问题对象拷贝在不同的编程语言中有深度拷贝(Deep Copy,也翻译成深度复制、深拷贝等)和浅拷贝(Shallow Copy,也翻译成影子拷贝、影子复制、浅度复制、浅复制等)的区别如果原型类之间有循环引用的作用域,则无法实现深度拷贝使用原型模式的行业案例1JDK的Vector原型类JDK中使用了大量的原型类java.util.Vector是一个动态数组java.u

14、til.Vector实现java.lang.Cloneable接口,并重写clone()方法java.util.Vector的类图 public class Vector extends AbstractListimplements List, RandomAccess, Cloneable, java.io.Serializable/* * 对象拷贝方法 */ public synchronized Object clone() try SuppressWarnings(unchecked) Vector v = (Vector) super.clone();/使用Object的clone(

15、)方法 /* * 手动实现元素拷贝 * 如果Vector对象元素不是引用类型数据,则为深度拷贝 * 否则,为浅拷贝 */ v.elementData = Arrays.copyOf(elementData, elementCount); v.modCount = 0; return v; catch (CloneNotSupportedException e) /异常处理 /省略的代码 使用原型模式的行业案例1JDK的HttpCookie原型类.HttpCookie是一个使用Object的clone()方法实现浅拷贝的原型类.HttpCookie负责构造HTTP协议的Cookie,常被用于创建

16、有状态的会话(Session) public final class HttpCookie implements Cloneable /* * 实现浅拷贝 */ Override public Object clone() try return super.clone();/使用Object的clone()方法 catch (CloneNotSupportedException e) throw new RuntimeException(e.getMessage(); /其他代码 构造器(Builder)模式构造器(Builder)是指为构造一个复杂的产品对象,进行产品组成元素构建和产品组装的

17、对象使用构造器的场景有需要将复杂产品对象的构造过程(或算法)封装在独立的代码中对不同的产品表示复用同一个构造过程(或算法)构造器模式类结构构造器模式对象协作时序使用构造器的练习COS菜单数据存储在MySQL数据库表中,服务器程序通过网络向不同的客户端提供菜单数据;浏览器客户端需要的菜单数据文本格式为XML,Android和iOS客户端需要的菜单数据文本格式为JSON由于COS菜单数据表结构不变,结构化的菜单数据转换为XML或JSON文本的过程或算法相同XML与JSON是不同的文本对象表示使用构造器构造文本对象的类结构 public interface TextBuilder /* * 将菜单项

18、类型转换为文本 */public void convertmType(int mType);/* * 将菜单项名称转换为文本 */public void convertmName(String mName);/* * 将菜单项价格转换为文本 */public void convertmPrice(float mPrice); public class JSONBuilder implements TextBuilder private JSONText json;/ json文本对象private String jsonElement;/json元素public JSONBuilder() j

19、son = new JSONText();/* * 获取构造好的JSON文本对象 */public JSONText getJsonText() return json;Overridepublic void convertmType(int mType) jsonElement=nMType:+mType+;jsonElement+=,;Overridepublic void convertmName(String mName) jsonElement+=MName:+mName+;jsonElement+=,;/省略的代码 public class BuilderDirector priv

20、ate TextBuilder builder;/构造器/* * 调用构造器,构造目标文本对象的组合元素 */public void construct(List data) /构造算法 for (MenuItem mi : data) builder.convertmType(mi.getmType(); builder.convertmName(mi.getmName(); builder.convertmPrice(mi.getmPrice(); /省略的代码使用构造器模式需要注意的问题如果产品构造过程(或算法)不需要复用或独立封装,可以去除Director类,减少设计类的数量;Dire

21、ctor类的职责由使用Builder的客户端实现不同的产品表示需要由不同的Builder实现进行构造和装配使用构造器模式的案例1JDK的AbstractStringBuilder构造器类JDK中的java.lang.StringBuffer和java.lang.StringBuilder都是继承抽象类java.lang.AbstractStringBuilder的子类,负责构造可变的字符串JDK并没有单独实现构造器模式中的Director类,字符串的构造过程(或算法)由使用java.lang.StringBuffer或java.lang.StringBuilder的客户端代码实现Java文本构

22、造器的类结构 public final class StringBuffer extends AbstractStringBuilderimplements java.io.Serializable, CharSequence /* 向字符序列聚合体中添加boolean类型元素*/ Override public synchronized StringBuffer append(boolean b) toStringCache = null; super.append(b); return this; /* 装配和生成完整的String对象*/ Override public synchron

23、ized String toString() if (toStringCache = null) toStringCache = Arrays.copyOfRange(value, 0, count); return new String(toStringCache, true);/省略的代码使用构造器模式的行业案例2Android SDK的AlertDialog.Builder构造器类Android SDK中的android.support.v7.app.AlertDialog.Builder就是用于复杂产品表示android.support.v7.app.AlertDialog对象的构造器

24、android.support.v7.app.AlertDialog是个聚合体,由title、message、button等元素组成Android对话框与构造器的类关系 /* * 外部类AlertDialog */ public class AlertDialog extends AppCompatDialog implements DialogInterface final AlertController mAlert;/对话框控制器/* 静态嵌入类Builder*/public static class Builder private final AlertController.Alert

25、Params P;/对话框参数 private final int mTheme;/对话框主题 /* * 设置对话框标题 */ public Builder setTitle(StringRes int titleId) P.mTitle = P.mContext.getText(titleId); return this; /* * 装配并生成完整的AlertDialog对象 */ public AlertDialog create() final AlertDialog dialog = new AlertDialog(P.mContext, mTheme); P.apply(dialog

26、.mAlert); /代码省略 return dialog; 抽象工厂(Abstract Factory)模式抽象工厂(Abstract Factory)指在不指定具体产品类的情况下,为相互关联的产品簇或产品集(Families of Products)提供创建接口,并向客户端隐藏具体产品创建的细节或表示的对象抽象工厂使用场景有需要实现产品簇样式的可扩展性,并向客户端隐藏具体样式产品簇的创建细节或表示向客户端保证产品簇对象的一致性,但只提供产品对象创建接口使用产品簇实现软件的可配置性抽象工厂模式类结构抽象工厂模式对象协作时序使用抽象工厂的练习COS系统需要实现订单数据统计展示功能,数据展示的图

27、表类型有饼状图、柱状图和线状图。图表风格在COS 1.0版本中需实现水晶和扁平样式,但COS 2.0或后续迭代版本中,还需实现3-D样式饼状图、柱状图和线状图共同构成图表产品簇COS进行数据展示时,需要保持图表展示体验的一致使用抽象工厂创建图表对象的类结构 public class ChartDrawer private ChartFac chartFac;/工厂对象public ChartDrawer(ChartFac fac)chartFac=fac;/* * 绘制饼状图元素 */public void drawPie(Data data)Pie pie=chartFac.createPi

28、e(data);pie.draw();/* * 绘制线状图元素 */public void drawLine(Data data)Line line=chartFac.createLine(data);line.draw();/其他代码省略 public abstract class ChartFac /* * 创建线状图 */public abstract Line createLine(Data data);/* * 创建饼状图 */public abstract Pie createPie(Data data);/* * 创建柱状图 */public abstract Bar creat

29、eBar(Data data); public class CrystalChartFac extends ChartFac /* * 创建水晶样式的线状图对象 */Overridepublic Line createLine(Data data) CrystalLine line = new CrystalLine();line.setData(data);return line; /* * 创建水晶样式的饼状图对象 */ Overridepublic Pie createPie(Data data) CrystalPie pie = new CrystalPie();pie.setData

30、(data);return pie; /* * 创建水晶样式的柱状图对象 */Overridepublic Bar createBar(Data data) CrystalBar bar = new CrystalBar();bar.setData(data);return bar; 使用抽象工厂模式需要注意的问题产品簇中抽象产品类型的增加或减少会导致已有代码的大量修改产品簇样式的增加,会导致设计类的数量急剧增加由于工厂对象提供无状态服务,可以设计成单例使用抽象工厂模式的行业案例JDK实现AWT(Abstract Window Toolkit,抽象窗口工具集)时,使用了抽象工厂模式抽象工厂类有

31、:java.awt.Toolkit、sun.awt.SunToolkit、sun.awt.UNIXToolkit产品簇中的抽象产品类型有:java.awt.peer.ButtonPeer、java.awt.peer.CanvasPeer、java.awt.peer.DialogPeerAWT使用工厂模式的类结构 public abstract class Toolkit /创建ButtonPeer对象protected abstract ButtonPeer createButton(Button target) throws HeadlessException;/创建DialogPeer对象

32、protected abstract DialogPeer createDialog(Dialog target) throws HeadlessException;/省略其他代码public final class XToolkit extends UNIXToolkit implements Runnable /* 创建XButtonPeer对象*/public ButtonPeer createButton(Button target) ButtonPeer peer=new XButtonPeer(target); targetCreatedPeer(target,peer); ret

33、urn peer;/* 创建XLabelPeer对象*/public LabelPeer createLabel(Label target) LabelPeer peer=new XLabelPeer(target); targetCreatedPeer(target,peer); return peer;/省略其他代码工厂方法(Factory Method)模式工厂方法(Factory Method)类定义了产品对象创建接口,但由子类实现具体产品对象的创建工厂方法模式使用的场景有当业务类处理产品对象时,无法知道产品对象的具体类型,或不需要知道产品对象的具体类型(产品具有不同的子类型)当业务类

34、处理不同的产品子类型对象业务时,希望由自己的子类实现产品子类型对象的创建工厂方法模式类结构工厂方法模式对象协作时序使用工厂方法模式的练习COS 1.0系统向客户提供订单导出功能,订单导出时可以选择导出文件类型是Html或Pdf,将来的COS 2.0升级版本中需要添加Office Excel导出功能导出文件过程(或算法)的业务代码可以复用文件对象具有不同的子类型(文件格式或文件编码)将来会添加新类型文件的导出功能,设计方案必须具备可扩展性使用工厂方法导出不同类型文件对象的类结构 public abstract class DocumentCreator /* * 文件导出过程(或算法) */pu

35、blic boolean exportDocument(String fileName)boolean result=true;/导出结果Document doc=createDocument(fileName);/调用子类实现的方法创建Document对象try FileOutputStream fos=new FileOutputStream(doc.getFileName();/创建输出流doc.writeFileContent(fos);/写文件内容至输出流fos.close();/关闭输出流 catch (FileNotFoundException e) result=false;e.printStackTrace(); catch (IOException e) result=false;e.printStackTrace();return result;/* * 创建Document对象 */public abstract Docu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论