UML软件工程组织

 

 

《java与模式》----创建模式系列工厂模式、单态模式精讲
 
作者:Query1981的专栏  来源:网络
 

创建模式是对类实例化过程的抽象。

一些系统在创建对象的时候需要动态的决定怎样创建对象、创建哪些对象、以及如何组合,表示这些对象。创建模式描述了怎样构造和封装这些动态的决定。

创建模式又分类的创建模式和对象的创建模式。

  • 类的创建模式:类的创建模式使用继承关系,把类的创建延迟到子类,从而封装了客户端将得到哪些具体类的信息,并隐藏了这些类的实例是如何被创建的和放在一起的。
  • 对象的创建模式:对象的创建模式则把对象的创建过程动态的委派给另一个对象,从而动态的决定客户端将得到哪些具体类的实例,以及这些类实例如何被创建和组合在一起。

工厂模式

工厂模式负责将大量有共同接口的类实例化。工厂模式可以决定将哪一个类实例化,不必事先知道每次要实例化哪一个类。

工厂模式的几种形态:

  • 简单工厂模式。又称静态工厂模式。
  • 工厂方法模式。Factory Method,又称多态工厂或虚拟构造子模式(Virtual Constructor)。
  • 抽象工厂模式。Abstract Factory,又称工具箱(Kit或ToolKit)模式。

工厂模式的逐步递演反映了抽象的步步加深、解决问题

简单工厂--------Simple Factory

简单工厂模式是由一个工厂对象决定创建何种产品类的实例。

简单工厂模式的普通类图:

工 厂 S-Factory

+create():C-P

P--interface

 P--concrete

 静态创建---create

 具体产品

抽象产品

简单工厂模式设计到的角色:

1. 工厂类(creator)角色:这个角色是工厂模式的核心,它含有于应用紧密相关的商业逻辑。工厂类在客户端的调用下创建产品对象,它往往又一个具体的java类实现。

2. 抽象产品(Abstract Product)角色:它为具体产品提供了一个共同的接口(类型)。是工厂方法的返回类型。

3. 具体产品(Concrete Product)角色:工厂方法所创建的对象都是它的实例。

简单工厂模式的特征:静态方法返回对象实例。

抽象产品

 具体产品

简单工厂模式的其它类图:

  • 这一种比较极端:!java类库中也有
  • 大量实例.退化的简单工厂模式。
  • 第二种:工厂角色和抽象产品合并。

单态模式和多态模式的构造函数都是私有的---对外不提供直接实例化的功能,它们都有自己的静态的工厂方法,提供自身的实例。

当单态模式和多态模式使用一个集合来存储自己创建的对象,以便通过查询这个集合来得到创建的对象时,就成了备忘录模式的应用。

 MVC模式。MVC模式并不是严格意义上的设计模式,而是更高层次上的构架模式。MVC模式可以分解成几个设计模式的组合,包括合成模式、策略模式、观察者模式,也有可能包括装饰模式、调停者模式、迭代子模式以及工厂方法模式等。

简单工厂模式说创建的对象往往属于一个产品等级结构,这个产品的等级结构可是使MVC模式中的视图(View),而工厂角色本身可以使控制器(Controller)。

 AbstractView

 View

 View

 Controller

简单工厂模式使用静态工厂方法,而静态方法无法由子类继承,因此工厂角色无法形成给予继承的等级结构。这一缺点在工厂模式中得到了解决。

简单工厂模式中工厂角色是该系统的关键角色。它关系了系统的命运,也集中了所有的逻辑。这使得系统在将来进行功能拓展时变得异常复杂。

简单工厂模式对“开闭”原则支持不够。当产品角色的类功能拓展时,该模式完全支持。但当有新的产品角色加入时,就不得不修改工厂角色来适应了。它在有限程度上支持“开闭”原则。

工厂方法返回抽象产品类型的做法称作“针对抽象编程”。这是依赖倒转原则的应用。这样做是利用具体产品类的超类型将它的真实类型隐藏起来,其好处是为系统提供了可拓展性。如果将来有新的具体产品类加入到系统中来,那么工厂类可以将其交给客户端对象换成新的子类实例,而对客户端没有影响。

工厂方法模式

工厂方法模式是定义一个工厂角色的接口,将世纪的创建工作推迟到工厂角色的子类去完成。

在工厂方法模式中核心的工厂类不再负责所有产品的创建,而是讲具体的创建工作交给子类去完成。这个核心类变成了抽象工厂角色。抽象工厂角色仅给出具体工厂角色必须实现的接口,而不去接触哪一个产品类应当被实例化这样的细节。

这种进一步抽象的结果使得工厂方法模式允许系统在不修改具体工厂角色的情况下引进新产品。

工厂方法模式的基本类图:

Abstract Factory
 Concrete Factory
 P--interface 
 P--concrete
 create

工厂模式的角色:

  • 抽象工厂(Abstract Factory)角色:这个角色使工厂模式的核心,它与应用程序无关。可以由接口或抽象类担任。
  • 具体工厂(Concrete Factory)角色:担任这个角色的类是实现了抽象工厂的接口的具体类。具体工厂角色含有与应用密切相关的逻辑,并且受到应用程序的调用以创建对象。
  • 抽象产品角色:工厂方法模式说创建的对象的父类型,也就是具体产品的共同接口。
  • 具体产品角色:这个角色思想了抽象产品角色所声明的接口。工厂方法所创建的的每一个对象都是某个具体产品角色的实例。

抽象工厂模式

抽象工厂是工厂模式中最为抽象和普遍的一种形态。

工厂模式面对的问题是一个产品的等级结构,而抽象工厂需要面对多个产品的等级结构。

抽象工厂的类图:

Creator1
 +createA:ProductA
 +createB:ProductB
 Creator2
 +createA:ProductA
 +createB:ProductB
 Interface ProducutA
 ProducutA1
 ProducutA2
 Interface ProducutB
 ProducutB1
 ProducutB2
 Interface Creator
 +createA:ProductA
 +createB:ProductB

抽象工厂面向的是产品等级结构中的产品族:

具体工厂Creator1在继承了抽象工厂Creator的+createA:ProductA +createB:ProductB 的产品结构后,专注于产品族Producut*1 的开发。

横向的产品族与纵向的产品结构通过抽象工厂联系到一起。

在什么情况下使用抽象工厂模式:[GOF][阎宏]

  • 一个系统不应当依赖于产品实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是至关重要的。
  • 这个系统产品有多余一个的产品族,而系统只消费其中某一族的产品。这也是抽象工厂的原始用意。
  • 同属于同一产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
  • 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

单态模式-----(Sigleton)

单态模式确保系统中,一个类子只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类成为单态类。

单态模式的要点:

  • 某一个类只有一个实例。
  • 它必须自行创建这个实例。
  • 它必须向整个系统提供这个实例。
  • 构造函数私有:不被外部实例化,也不被继承。

单态模式的实例:资源管理器,回收站,打印机资源。

单态模式的结构:
 0..1
 1

 饿汉式单态类:

Eager Singletion
 -m instance: EagerSingletion = new EagerSingletion()

 -EagerSingletion() //构造函数为私有

+getInstance():EagerSingletion //返回该实例,静态工厂方法

 create

 代码:饿汉式单态类

public class EagerSingletion{

private static final EagerSingletion m_instance= new EagerSingletion();

private EagerSingletion(){} //私有构造函数,防止被new

/**

* 静态工厂方法

*/

public static EagerSingletion getInstance(){

return m_instance;

}

}

懒汉式单态类:

Lazy Singletion
 -m instance: Lazy rSingletion = null;

 - LazySingletion() //构造函数私有化

+getInstance():LazySingletion //返回该实例,静态工厂,线程安全

 create

 代码:懒汉式单态类

public class LazySingletion{

private static final LazySingletion m_instance= null;

private LazySingletion(){} //私有构造函数,防止被new

/**

* 线程安全,静态工厂方法,保证返回唯一实例

*/
 public static synchronized EagerSingletion getInstance(){

if(m_instance = null){
  m_instance = new EagerSingletion();

}
return m_instance;

}
}
 登记式单态类:

登记式单态类是GOF为了克服前两者不可继承的缺点而设计的。只是它的子类实例化的方式只能是懒汉式的---这是无法改变的。

RegSingletion
 -m registy:HashMap m_ registy = new HashMap();

 # RegSingletion() //构造函数保护类型—可被子类继承

+getInstance(name:String):RegSingletion //返回该实例

+about():String

 create

代码:登记式单态类 /*注释:p213 出现印刷错误 static 关键字位置错了*/

public class RegSingletion{

private static HashMap m_ registy = new HashMap();

/**

* 静态块,在类声明前自动加载

*/

static{

RegSingletion x = new RegSingletion();

m_ registry.put(x.getClass().getName(),x);

}

protected RegSingletion(){} //保护的构造函数,可被子类继承!

/**

* 线程安全,静态工厂方法,保证返回唯一实例

*/

public static synchronized RegSingletion getInstance(String name){

if(name = = null){

name = “com.javaptterns.singletion.RegSingletion”;

}

if(m_ registry.getname(name)= =null){

try{

m_ registry.put(name,Class.forName().newInstance());

}catch(Exception e){

}

}

return m_instance;

}

public String about(){

return “work complete”;

}

}

使用单态模式的条件:

在一个系统需要已给类的一个实例时才应使用。

例子:

  • 系统中的全程变量是否可以放到一个单态类里?

----不可以!一个设计得当的系统是不应当有所谓的“全程变量”的,这些变量应当放到他们所描述的实体所对应的类中去。如果将这些变量抽取出来放到一个不相干的单态类中,会使得这些类产生错误的依赖、耦合关系。

  • 与数据库的连接对象(Connection)也不应当被设计成单态模式。因为一个数据库连接可以有几个实例。

Java语言中的单态类:

Runtime对象每一个java应用程序内部都有唯一一个Runtime对象,通过这个对象,应用程序可以与运行环境发生相互作用。Runtime类提供一个静态工厂方法。

public static Runtime getRntime();

Runtime对象的用途常包括:执行外部命令、返回现有内存、运行垃圾收集器、加载动态类库等。

Process pro = Runtime. getRntime().exec(“notPad.exe”);

java.awt.Toolkit类:

 

组织简介 | 联系我们 |   Copyright 2002 ®  UML软件工程组织 京ICP备10020922号

京公海网安备110108001071号