设计模式在java中的运用
读《java与模式》之一
第 I 条 理解三种工厂模式,关键是工厂方法。(区分factory method和factory method pattern)
【1】 简单工厂模式:
又称静态工厂方法模式,其工厂方法是静态方法。
creator必须包含逻辑判断,以决定在何时,创建何种类的实例。Client只有消费的责任。因此,简单工厂分解了责任。
java.text.DateFormat与java.text.SimpleDataFormat
DateFormat.getTimeInstance();
DateFormat.getTimeInstance(int style);
DateFormat.getTimeInstance(int style, Locale locale);
DateFormat是抽象类,上述三个方法都是静态方法,查源码知:三个方法最后创建的是SimpleDateFormat对象,即DateFormat的子类对象。因此,DateFormat即是creator,又是AbstractProduct,SimpleDateFormat是ConcreteProduct。getTimeInstance是工厂方法。
【2】 工厂方法模式:
引入抽象工厂类,由其子类完成产品对象的创建,而不是像在简单工厂中由一个工厂类完成所有产品对象的创建。因此,工厂类可以和产品类形成平行的等级结构。
java.util.Collection接口中定义了创建产品Iterator的工厂方法iterator()。每个继承Collection的子类,有其各自的iterator(),并创建不同类型的具体Iterator。
【3】 抽象工厂模式
对比抽象工厂模式和工厂模式,可以发现在前者,一个具体工厂有多个创建方法(这里是工厂方法,注意工厂方法和工厂方法模式),而后者只有一个创建方法。更进一步,在前者,一个具体工厂对应多个具体产品,而在后者,一个具体工厂对应一个具体产品。这是两者在形式上的区别。
简单工厂模式中,一个工厂类创建所有的产品类;工厂方法模式中,这个工厂类被抽象,由其子类,即具体工厂创建具体产品,且一一对应;抽象工厂模式将创建方法再抽象,一个具体工厂创建多个具体产品,这些具体产品通常被认为是有关联的,即是一个产品族。
第 II 条命令模式
请求方发请求要求执行某操作;接收方收到请求执行该操作。
命令的请求与执行被分开,请求方和接收方可以独立演化,因此:
新命令容易添加;
接收方可以否决请求;
容易设计命令队列;
容易实现命令的undo和redo;
容易将命令记录到日志。
关于命令模式的使用:
命令对象的生命期,不受发出命令的请求对象的生命期限制。
命令模式可以支持使用undo和redo,以及veto。前两者要结合Memento模式。
有了命令模式可以支持将操作写入日志,这样便于系统崩溃时重做。
在transaction中使用命令模式,可以增加新的transaction。
将多个命令聚会在一起,即结合Composite模式,可以组成宏命令。
为了复制命令,结合Prototype模式。
一个问题:
可能导致过多的具体命令类的存在。
AWT的事件处理机制。
在该机制中,命令对象(具体命令)实现AWT的listener接口(命令接口)。事件是请求者,组件是接收者。AWT中未将接收者组件的引用放在命令中,而是使用事件委派机制另外管理。先以事件注册的方式指明对某请求,命令和接收者是如何的对应关系。当某事件发生,发出某具体命令,从事先的注册中查找该命令对应的接收者组件,然后调用之。
AWT使用事件注册/分派机制是必要的,因为不能事先确定事件发出的命令将有多少接收者。在程序中就是使用addListener()动态添加接收者。
Swing的命令undo与redo:
第 III 条 Singleton模式与multiton模式
对singleton几点注意:
【1】 三种singleton:饿汉式,懒汉式,登记式。
登记式:
【2】 Singleton类可以分为:有状态、无状态。有状态的singleton可用作状态库repository。属性管理器常使用singleton模式。
【3】 不完全的singleton类:如果singleton类存在public的构造器,那么除了使用工厂方法外(singleton所希望),还是从client调用构造器创建singleton对象。这个singleton就是不完全singleton。
Java.lang.Runtime对象也是singleton模式,每个java应用程序有唯一的Runtime对象( Runtime.getRuntime() )。
java.awt.Toolkit也是singleton模式。
Multiton模式是singleton模式的推广:
多例类可以有多个实例;
多例类自己创建、管理自己的实例、向外界提供自己的实例。
Multiton又分:有上限多例类、无上限多例类;有状态、无状态。
为了保存多个实例,multiton类可使用一个聚集对象记录创建的各实例。这与singleton的登记式类似。但是,singleton的登记式的用意是改善singleton不能继承的问题,不论是其中的父类还是子类还是只能有一个实例的。
应用案例:见《java与模式》
多例模式与多语言支持、序列键生成器与单例多例模式
第 IV 条 Proxy模式
java.lang.reflect.Proxy和java.lang.reflect.InvocationHandlers现实java的动态代理机制。
java的动态代理机制需要进一步研究:
第 V 条Builder模式
Builder模式可以将一个产品的internal representation与产品的创建过程分开,从而一个创建过程生成具有不同internal representation的产品对象。
builder模式有很多种情况的退化和变化,如builder与director的合并。
javamail利用builder模式创建一个待发送的消息,如下片段对message的创建:
第 VI 条 Observer模式
又叫发布/订阅模式(publish/subscribe),多个观察者对象同时监听一个主题对象。当主题对象状态改变时,所有观察者对象收到来自主题对象的通知。
java.util.Observer接口和java.util.Observable类是observer模式的完美再现。
AWT,servlet的DEM机制(Delegation Event Mode)。
javax.swing.Timer类
第 VII 条 Composite模式
Composite使client将叶子节点与树枝节点同等对待。
有两种Composite:安全模式和透明模式。前者在Componet中声明管理子类对象的方法;后者在Composite中声明管理子类对象的方法。
AWT和Swing的图形界面的结构是基于Composite的:
第 VIII 条 Bridge模式
将抽象化(Abstraction)与实现化()implementation分脱耦,使得二者可以独立地变化。
抽象与实现在面向对象系统设计中的重要方式,是实现“开闭原则OCP”的重要武器,通常可以用继承来完成。但继承的缺点是父类与子类的耦合度高,因此经常把继承用组合/聚集来替代。Bridge模式就是如此。
值得注意的是:Implementor中的OperationImlp()不一定要一一对应于Abstraction的Operation(),实际上两个接口Implementor和Abstraction可以很不一样。要点是:Implementor给出底层操作,而Abstraction给出基于底层的高层操作。
再论OCP:OCP要求对扩展开,对修改闭。抽象化与实现化的最简单方式就是继承。继承可以在子类的层次对扩展开放,而父类层次上也扩展的情况就不能处理了。
因此,为了让父类与子类两个层次上的变化独立,
【1】 各自继承:
【2】 用聚集关联:
这样:两个层次上的变化被隔离了。
设计提示:
【1】 好的设计通常没有多于两层的继承;
【2】 当变化有两个以上的时候,注意区分使用继承还是聚合。
Bridge模式是“对变化封装”原则和组合/聚集复用原则的极好范例。
AWT的peer架构:
JDBC驱动器:
其他驱动器:
很多驱动器软件都是bridge模式,如打印机驱动器。
第 IX 条 Adapter模式
将一个类的接口变成client期望的另一种接口,从而让因接口不同而不能合作的类能够一起工作。
对象的adapter:
类的adapter:
java在没有collection框架前(before 1.2)使用Enumeration接口,而之后使用Iterator接口。两个接口具有不同的方法,用adapter匹配:
从Enumeration到Iterator:
从Iterator到Enumeration:
另外的例子:
WINE:在linux上运行windows程序的平台。
MKS Toolkit:在windows上运行unix shell的平台。
J2se中存在很多的默认适配器类。
第 X 条 Decorator模式
又名wrapper,对client透明地扩展对象的功能,是继承的一个替代方案。可以最对对象添加功能,而不是对整个类。
java的io库详解:
流就是数据的有序排列。
如下是io流的示意。
IO库的设计原则:
两个对称性:
l 输入、输出对称:InputStream和OutputStream是Byte流输入、输出的两个平行等级结构的根部;Reader和Writer是char流输入、输出的根部。
l Byte、char对称:InputStream,Reader负责byte、char的输入;OutputStream、Writer负责byte、char的输出。
两个设计模式:
l 装饰模式:因为IO库需要很多的功能组合,继承会造成类爆炸。IO库就是由基本的原始流处理器和围绕它们的装饰流处理器(也称链接流处理器)组成的。
l 适配器模式:
装饰模式的使用:
输入流:
如上所示的输入流类图中,有四个原始流处理器,其他是装饰流处理器(能接受其他流,并用装饰模式增加了功能)
原始流处理器:
ByteArrayInputStream,FileInputStream,PipedInputStream,StringBufferInputStream
装饰流处理器:
FilterInputStream(BufferedInputStream,DataInputStream,LineNumberInputStream,PushbackInputStream),ObjectInputStream,SequenceStream
上图的装饰器模式结构如下:
又可以抽象为:
对应于输出流:
原始输出流:
ByteArrayOutputStream,FileOutputStream,PipedOutputStream
装饰器输出流:
FilterOutputStream(BufferedOutputStream,DataOutputStream,PrintStream),ObjectOutputStream。
上图的装饰器模式结构;
Reader的装饰模式
原始流处理器:
CharArrayReader,InputStreamReader(FileReader),PipedReader,StringReader
链接流处理器
BufferedReader(LineNumberReader),FilterReader(PushbackReader)
Writer的装饰器模式:
原始流处理器:
CharArrayWriter,OutputStreamWriter(FileWriter),PipedWriter,StringWriter
链接流处理器:
BufferedWriter,FilterWriter,PrintWriter
半透明的装饰模式介于装饰模式和适配器模式之间:
理想的装饰器模式增强功能,而不改变接口。但这很难做到,因此常常增加某些方法,这就称为半透明的装饰模式。
适配器模式就是为了将接口不同而功能类似的类统一起来,所以适配器模式改变接口而不改变功能。
半透明的装饰器模式增加了功能,又适当改变了接口(增加),因此是介于上两者间的模式。
IO库中的适配器模式:
以InputStream体系为例:
Ø ByteArrayInputStream使用了适配器模式。
ByteArrayInputStream(上图应为ByteArrayInputStream)将byte数组的接口适配为了InputStream流处理器的接口。
Ø FileInputStream将FileDescriptor适配为了InputStream。
Ø StringBufferInputStream将String适配为InputStream
以OutputStream体系为例:
Ø ByteArrayOutputStream将Array数组适配为OutputStream
Ø FileOutputStream将FileDescriptor适配为OutputStream
Ø StringBufferOutputStream将String适配为OutputStream
PipedOutputStream将PipedInputStream适配为OutputStream
Ø PipedOutputStream将PipedInputStream总是一起使用的。
Reader原始流处理器都是适配器模式
Ø CharArrayReaderßàChar array
Ø StringReaderßàString
Ø InputStreamReader从byte流到char流的适配器
Writer原始流处理器都是适配器模式
Ø CharArrayWriterßàChar array
Ø StringWriteßàStringBuffer
Ø InputStreamWriter从byte流到char流的适配器
PipedWriter将PipedReader适配为Writer
Ø 两者总是一起使用的。
byte流到char流的适配
InputStreamReader是InputStream到Reader的适配
OutputStream是OutputStream到Writer的适配
一个例子:
String line;
InputStreamReader reader = new InputStreamReader(System.in);
System.out.println(“some strings”);
BufferedReader bfreader = new BufferReader(reader);
line = bfreader.readLine();
System.out.println(line);
InputStreamReader是适配器,BufferedReader是装饰器。
分享到:
相关推荐
23种设计模式,运用在c#中也不错。...........
Java开发技术大全.part1.rar 免积分下载(解压需5个文件part1,...其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。
本书从一个新的视角描述面向对象设计,将面向中对象编程的原则与运用设计模式力量创建健壮、可靠的软件开发环境结合起来。书中采用实用、恰当的例子,指导读者用模式解决普通的编程问题,并且解释现代软件设计模式的...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
2.2 名称空间在元素和属性中的运用 39 2.2.1 名称空间在元素中的运用 39 2.2.2 默认名称空间 41 2.2.3 名称空间在属性中的运用 42 2.3 名称空间和dtd 43 2.4 小结 45 第3章 对xml文档进行分析 46 3.1 dom、...
其最大特色是以六条主线贯穿全书:面向对象编程思想、Java语言的语法、Java虚拟机执行Java程序的原理、在实际项目中的运用、设计模式和性能优化技巧。同时,本书还贯穿了Sun公司的SCJP(Sun Certified Java ...
1.设计模式更抽象,J2EE 是具体的产品代码,我们可以接触到,而设计模式在对每个应用时才会产生具体代码。 2.设计模式是比 J2EE 等框架软件更小的体系结构,J2EE 中许多具体程序都是应用设计模式来完成的,当你深入...
在Asp.net中如何用SQLDMO来获取SQL Server中的对象信息 使用Relations建立表之间的关系并却使用PagedDataSource类对DataList进行分页 通过作业,定时同步两个数据库 SQLSERVER高级注入技巧 利用反射实现ASP.NET控件和...
2.2 名称空间在元素和属性中的运用 39 2.2.1 名称空间在元素中的运用 39 2.2.2 默认名称空间 41 2.2.3 名称空间在属性中的运用 42 2.3 名称空间和dtd 43 2.4 小结 45 第3章 对xml文档进行分析 46 3.1 dom、...
2.2 名称空间在元素和属性中的运用 39 2.2.1 名称空间在元素中的运用 39 2.2.2 默认名称空间 41 2.2.3 名称空间在属性中的运用 42 2.3 名称空间和dtd 43 2.4 小结 45 第3章 对xml文档进行分析 46 3.1 dom、...