`

Java与模式精简版

 
阅读更多

 

 

 

Java设计模式

 

创建型模式

简单工厂(Simple Factory)模式

简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。

PS】缺点就是逻辑复杂,扩展困难。

工厂方法(Factory Method)模式

工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。

工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。

使用时机

当一个类不知道它所必须创建的对象的类的时候。

当一个类希望由它的子类来指定它所创建的对象的时候。

当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

PS】产品的扩展符合开闭原则。

抽象工厂(Abstract Factory)模式

抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多个产品族中的产品对象。

使用时机

一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。

这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品;(上面这一条叫做抽象工厂模式的原始用意。)

同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。

系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

工厂方法模式与抽象工厂模式的区别

抽象工厂模式与工厂方法模式的最大的区别在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则需要面对多个产品等级结构。

工厂方法模式是一个具体的工厂只创建一个具体的产品,其纵向扩展容易,无横向扩展。

抽象工厂模式是一个具体的工厂创建一个产品族,其横向扩展容易,纵向扩展困难。比方说一个Windows工厂可以创建windowsButton也可以创建windowsText

 

单例(Singleton)模式

作为对象的创建模式[GOF95],单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

在任何使用了EJBRMIJNDI技术的分散式系统中,应当避免使用有状态的单例模式;在多个类加载器中也是一样。

使用时机

使用单例模式有一个必要条件:在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来说,如果一个类可以有几个实例共存,那么就没有必要使用单例类。

 

多例(Multiton)模式

作为对象的创建模式,多例模式中的多例类可以有多个实例,而且多例类必须自己创建、管理自己的实例,并向外界提供自己的实例。

 

建造(Builder)模式

建造模式是对象的创建模式[GOF95]。建造模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。

与工厂模式的区别

工厂模式返还不同产品族的零件,而建造者模式则把它们组装起来。

使用时机

需要生成的产品对象有复杂的内部结构。每一个内部成分本身可以是对象,也可以仅仅是一个对象的一个组成成分。

需要生成的产品对象的属性相互依赖。建造模式可以强制实行一种分步骤进行的建造过程,因此,如果产品对象的一个属性必须在另一个属性被赋值之后才可以被赋值,使用建造模式便是一个很好的设计思想。

在对象创建过程中会使用到系统中的其他一些对象,这些对象在产品对象的创建过程中不易得到。

PSDirector控制建造顺序,ConcreteBuilder建造零件和产品,Director不直接和产品打交道。

原始模型(Prototype)模式

原始模型模式属于对象的创建模式[GOF95]。通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。

使用时机

产品类的等级结构可能会有经常性的变化,不适合用工厂模式。

结构模式

适配器(Adapter)模式

适配器模式(Adapter Pattern[GOF95]把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

适配器模式的用意是将接口不同而功能相同或者相近的两个接口加以转换。

使用时机

系统需要使用现有的类,而此类的接口不符合系统的需要。

想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作。这些源不一定有很复杂的接口。

(对对象的适配器模式而言)在设计里,需要改变多个已有的子类的接口,如果使用类的适配器模式,就要针对每一个子类作一个适配器类,而这不太实际。

 

缺省适配(Default Adapter)模式

缺省适配模式为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。

缺省适配的用意是为了方便建立一个不平庸的适配器类而提供的一种平庸实现。

 

合成(Composite)模式

合成(Composite)模式属于对象的结构模式[GOF95],有时又叫做部分-整体(PartWhole)模式。合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式可以使客户端将单纯元素和复合元素同等看待。

使用时机

需要描述对象的部分和整体的等级结构。

需要客户端忽略掉个体构件和组合构件的区别。客户端必须平等对待所有的构件,包括个体构件和组合构件。

装饰(Decorator)模式

装饰(Decorator)模式又名包装(Wrapper)模式[GOF95]。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

使用时机

需要扩展一个类的功能,或给一个类增加附加责任。

需要动态地给一个对象增加功能,这些功能可以再动态地撤销。

需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。

PS】这个好像洋葱,一层又一层的;JavaI/O就是典型的装饰模式。

代理(Proxy)模式

代理模式是对象的结构模式[GOF95]。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

使用时机

The object being represented is external to the system.

Objects need to be created on demand.

Access control for the original object is required.

Added functionality is required when an object is accessed.

享元模式(Flyweight Pattern

Flyweight在拳击比赛中指最轻量级,即“蝇量级”,有些作者翻译为“羽量级”。

享元模式是对象的结构模式[GOF95].享元模式以共享的方式高效地支持大量的细粒度对象。

使用时机

●一个系统有大量的对象

●这些对象耗费大量的内存

●这些对象的状态中的大部分都可以外部化

●这些对象可以按照内蕴状态分成很多的组,当把外蕴对象从对象中剔除时,每一个组都可以仅用一个对象代替。

●软件系统不依赖于这些对象的身份,换言之,这些对象是不可分辨的。

PS】享元,享元,顾名思义就是共享元数据对象,比如String

门面(Facade)模式

外部与一个子系统的通信必须通过一个统一的门面(Facade)对象进行,这就是门面模式。

门面模式提供一个高层次的接口,使得子系统更易于使用。

使用时机

●为一个复杂子系统提供一个简单接口

●子系统的独立性

●层次化结构

桥梁(Bridge)模式

文献[GOF95]在提出桥梁模式的时候指出,桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化”。

桥梁模式的用意就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以相对独立地变化。

使用时机

如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系。

设计要求实现化角色的任何改变不会影响客户端,或者说实现化角色的改变对客户端是完全透明的。

一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态耦合。

虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。

行为模式

不变(Immutable)模式

一个对象的状态在对象被创建之后就不再变化,这就是所谓的不变模式(Immutable Pattern)。

 

策略(Strategy)模式

策略模式属于对象的行为模式[GOF95]。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以互相替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

由客户端自己决定在什么情况下使用什么具体策略角色。

策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中“退休”的方便,策略模式并不决定在何时使用何种算法。

策略模式不适合于处理同时嵌套多于一个算法的情形。

使用时机

如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

一个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法,并只持有一个数据类型是抽象算法类的对象。

一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据。

如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。

 

模板方法(Template Method)模式

模板方法模式是类的行为模式[GOF95]。准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。

Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

使用时机

A single abstract implementation of an algorithm is needed.

Common behavior among subclasses should be localized to a common class.

Parent classes should be able to uniformly invoke behavior in their subclasses.

Most or all subclasses need to implement the behavior.

观察者(Observer)模式

观察者模式是对象的行为模式[GOF95],又叫做发布-订阅(Publish/Subscribe)模式。

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

使用时机

State changes in one or more objects should trigger behavior in other objects.

Broadcasting capabilities are required.

An understanding exists that objects will be blind to the expense of notification.

MVC模式

所谓的MVC模式,即模型-视图-控制器(Model-View-Controller模式。

MVC模式实际上是架构模式,而不是设计模式。

 

迭代子(Iterator)模式

迭代子(Iterator)模式又叫做游标(Cursor)模式[GOF95],是对象的行为模式。迭代子模式可以顺序地访问一个聚集中的元素而不必暴露聚集的内部表象。

使用时机

访问一个聚合对象的内容而无需暴露它的内部表示。

支持对聚合对象的多种遍历。

为遍历不同的聚合结构提供一个统一的接口(, 支持多态迭代)

 

责任链(Chain of Responsibility)模式

责任链模式是一种对象的行为模式[GOF95]

在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。

使用时机

Multiple objects may handle a request and the handler doesn’t have to be a specific object.

A set of objects should be able to handle a request with the handler determined at runtime.

A request not being handled is an acceptable potential outcome.

 

 

 

 

命令(Command)模式

命令(Command)模式属于对象的行为模式[GOF95]。命令模式又称为行动(Action)模式或交易(Transaction)模式。

       命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。

使用时机

●使用命令模式作为“Callback”在面向对象系统中的替代。“Callback”指先将一个函数登记上,在以后再调用此函数。

●需要在不同的时间指定请求、将请求排队。

●系统需要支持命令的undoredo.

●需要一条一条地执行命令。

 

 

 

 

 

备忘录(Memento)模式

备忘录模式(Memento Pattern)又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式[GOF95]

       备忘录(Memento)对象是一个用来存储另外一个对象内部状态的快照(snapshot)的对象。备忘录模式(Memento Pattern)的用意是在不破坏封装(encapsulation)的条件下,将一个对象的状态捕捉(Capture)住,并外部化(Externalize),存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。

使用时机

●必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态。

●如果用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。

 

 

 

 

 

 

 

 

 

 

状态(State)模式

状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样。

使用时机

●一个对象的行为依赖于它所处的状态,对象的行为必须随着其状态的改变而改变。

●对象在某个方法里依赖于一重或多重的条件转移语句,其中有大量的代码。

 

对象在不同状态下的行为包装到不同的状态类里面,这是状态模式所要求的。状态模式所不指明的是控制状态转移的逻辑放在那里。在实现时,这种逻辑可以放在两个地方:一是放在环境类里面,二是包装在状态类里面。

 

访问者(Visitor)模式

访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。

访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。

在实际系统中访问者模式通常是用来处理复杂的对象树结构的,而且访问者模式可以用来处理跨越多个等级结构的树结构问题。这正是访问者模式的功能强大之处。

使用时机

访问者模式仅应当在被访问的类结构非常稳定的情况下使用。

      

访问者模式提供了倾斜的可扩展性设计:方法集合的可扩展性和类集合的不可扩展性。

 

解释器(Interpreter)模式

给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。

使用时机

●系统有一个简单的语言可供解释。

●一些重复发生的问题可以用这种简单的语言表达。

●效率不是主要的考虑。

 

 

 

 

 

 

 

 

 

 

调停者(Mediator)模式

调停者模式包装了一系列对象相互作用的方式,使得这些对象不必互相明显引用。从而使它们可以较松散地耦合。当这些对象中的某些对象之间的相互作用发生改变时,不会立即影响到其他的一些对象之间的相互作用。从而保证这些相互作用可以彼此独立地变化。

使用时机

●不应当在责任划分混乱时使用

●不应当对“数据类”和“方法类”使用

●正确理解封装

 

 

 

所有的理论在应用到实践中的时候,都必须对具体问题做具体分析。

要恰到好处地在一个系统里面使用设计模式,必须做到以下几点:

●完全了解面临的问题,这就是说要完全了解具体情况。如果不完全了解所面临的问题,怎么能谈得上解决问题呢?

●完全了解模式,这就是说要十分懂得理论。如果不完全懂得所使用的理论,怎么能够正确地应用这一理论呢?

●非常了解怎样使用设计模式解决实际的问题,这就是说要将模式理论与具体系统需求情况相结合。

 

一个对象所封装的是对象的行为,而面向对象的设计的中心问题是如何体现系统的行为。因为一个系统的行为不仅仅存在于一个对象里面,而是同时存在于很多对象里面,并且存在于这些对象之间的相互作用之中。

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics