`
jokermanager
  • 浏览: 143788 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

java设计模式之工厂模式(简单工厂方法)

阅读更多
工厂模式总述
  工厂模式属于类的创建模式,工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将哪一个类实例化,而不必事先知道每次要实例化哪一个类。工厂模式有三个基本形态:
1. 简单工厂(Simple Factory)模式,又称静态工厂方法模式(Static Factory Method
Pattern)。
2. 工厂方法(Factory Method)模式,又称多态性工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式。
3. 抽象工厂(Abstract Factory)模式,又称工具箱(Kit 或Toolkit)模式。
我们用图例来理解简单工厂模式的基本语义。(以下所有图示只是理解的代表形式,为了表达清楚,在某些方面可能违背建模图示法中的基本语义)。
 


图1

简单工厂模式的掌握,对学习单例模式和多例模式起着非常重要的作用。
图1表示农场的水果种植情况,很明显,我们可知:Fruit接口类有三个方法 (plant,harvest,grow);由于Apple和Grape类实现了Fruit接口,所以必须实现Fruit类中所有的方法,其中Apple 和Grape各自有相关的方法。至于他们之间的关系,代码我就不列出。
农场的园丁(FruitGardener )也是系统的一部分,自然要由一个合适的类来代表。这个类就是FruitGardener 类,FruitGardener 类会根据客户端的要求,创建出不同的水果对象,比如苹果(Apple)、葡萄(Grape)的实例。而如果接到不合法的要求,FruitGardener 类会抛出BadFruitException 异常。
/*********************以下为农场的园丁类*********************/
public class FruitGardener
{
/**
* 静态工厂方法
*/
public static Fruit factory(String which) throws BadFruitException
if (which.equalsIgnoreCase("apple"))
{
return new Apple();
else if (which.equalsIgnoreCase("grape"))
{
return new Grape();
}
else
{
throw new BadFruitException("Bad fruit request");
}
}
}
 
/*********************以下为自定义异常类*********************/
public class BadFruitException extends Exception
{
public BadFruitException(String msg)
{
super(msg);
}
}
 
 
/*********************用户调用*********************/
………………
try
{
FruitGardener.factory("grape");
FruitGardener.factory("apple");
FruitGardener.factory("xxx");
}
catch(BadFruitException e)
{
...
}
…………………
 
由此可见, 简单工厂涉及到三个角色:
1. 工厂类角色:负责创建产品的对象。如上面的FruitGardener类。它是工厂方法模式的核心。它往往由一个具体的类实现。
2. 抽象产品角色:实现了产品的共同接品,它可以由抽象类或接口实现。如上面的Fruit
3. 具体的产品:某一具体的产品,如上面的Apple和Grape
 
注意
1. 厂方法的中的工厂角色也可以由抽象产品角色扮演。即抽象产品角色担任了对象的创建。在java API中如:java.text.DateFormat 此时,抽象产品角色被定义成一个抽象的类,而不是一个接口。(抽象类与接口之间的区别与应用,在后面我会继续列出相关内容)。一个抽象类不能有自己的实例, DateFormat 的工厂方法是静态方法,并不是普通的方法。也就是说,它直属于类本身,不通过类的实例化。

图2
2. 如果抽象产品角色被省略,则工厂角色可以与具体产品角色合并。
public class FruitGardener
{
public FruitGardener (){}
/**
* 静态工厂方法
*/
public static FruitGardener factory()
{
return new FruitGardener ();
}
}
 
以上两点类似单例模式和多类模式,但不等于单例或多例模式。在后面模式设计中,会提到它,先别急。这是简单工厂模式的一种退化现象。如下代码:
 
简单工厂模式与其它模式的关系
1. 与单例模式的关系
单例模式使用了简单工厂模式。换言之,单例类具有一个静态工厂方法提供自身的实例。一个抽象产品类同时是子类的工厂。(如图2所示)
但是单例模式并不是简单工厂模式的退化情形,单例模式要求单例类的构造方法是私有的,从而客户端不能直接将之实例化,而必须通过这个静态工厂方法将之实例化,而且单例类自身是自己的工厂角色。换言之,单例类自己负责创建自身的实例。单例类使用一个静态的属性存储自己的惟一实例 ,工厂方法永远仅提供这一个实例。(说到这里,我简单有点兴奋,终于知道 Sun提供的javaAPI中为什么会采用这些模式 )
  2. 与多例模式的关系
  多例模式是对单例模式的推广。多例模式与单例模式的共同之处在于它们都禁止外界直接将之实例化,同时通过静态工厂方法向外界提供循环使用的自身的实例。它们的不同在于单例模式仅有一个实例,而多例模式则可以有多个实例。
多例模式往往具有一个聚集属性,通过向这个聚集属性登记已经创建过的实例达到循环使用实例的目的。一般而言,一个典型的多例类具有某种内部状态,这个内部状态可以用来区分各个实例;而对应于每一个内部状态,都只有一个实例存在。
:聚集表示类之间的关系是整体与部分的关系,它分:共享聚集和组成;共享聚集中的部分可以是多个整体的一部分;而组成 表示整体与部分关系,整体消失,则部分也消失。需要注意的是 ,一些面向对象大师对聚集的定义并不一样。
其它理解多例模式,并不困难,我们可以通过javaAPI来理解,尤其是聚集关系。
根据外界传入的参量,工厂方法可以查询自己的登记聚集,如果具有这个状态的实例已经存在,就直接将这个实例提供给外界;反之,就首先创建一个新的满足要求的实例,将之登记到聚集中,然后再提供给客户端。
关于单例模式和多例模式详细的细节,在后面会描述。
3. 备忘录模式
单例和多例模式使用了一个属性或者聚集属性来登记所创建的产品对象, 以便可以通过查询这个属性或者聚集属性找到和共享已经创建了的产品对象。这就是备忘录模式的应用。
4. MVC 模式
MVC 模式并不是严格意义上的设计模式,而是在更高层次上的架构模式。 MVC 模式可以分解成为几个设计模式的组合,包括合成模式、策略模式、观察者模式,也有可能会包括装饰模式、调停者模式、迭代子模式以及工厂方法模式等。
简单工厂模式所创建的对象往往属于一个产品等级结构,这个等级结构可以是MVC模式中的视图(View);而工厂角色本身可以是控制器(Controller)。一个MVC 模式可以有一个控制器和多个视图,如下图所示。

图3
我们结合简单工厂方法,可知上图中的Controller(控制器)也就是工厂角色,(FruitGardener)它负责创建产品View(视图)。如果系统需要有多个控制器参与这个过程的话,简单工厂模式就不适用了,应当考虑使用工厂方法模式,我们以后描述它。
 
简单工厂方法的应用
使用静态工厂方法是为了将具体子类实例化的工作隐藏起来,从而客户端不必考虑如何将具体子类实例化,因为抽象类DateFormat 会提供它的合适的具体子类的实例。这是一个简单工厂方法模式的绝佳应用。
利用具体产品类的超类类型将它的真实类型隐藏起来,其好处是提供了系统的可扩展性。如果将来有新的具体子类被加入到系统中来,那么工厂类可以将交给客户端的对象换成新的子类的实例,而对客户端没有任何影响。
这种将工厂方法的返还类型设置成抽象产品类型的做法,叫做针对抽象编程,这是依赖倒转原则(DIP)的应用。我们后面会描述“依赖倒转原则(DIP)”的具体应用。
 
该模式的缺点
大家不难看出,如果新增加产品如:orange,则需要修改工厂类(FruitGardener),从而限制了其灵活性;而对于产品角色类适合,因此简单工厂只在有限的程度上支持“开–闭”原则。
工厂类集成了所有的创建工作,显得工厂类负任比较得,万一出问题,所有的创建工作将不能进行。当产品类有不同的接口种类时,工厂类需要判断在什么时候创建某种产品。这种对时机的判断和对哪一种具体产品的判断逻辑混合在一起,使得系统在将来进行功能扩展时较为困难。这一缺点在工厂方法模式中得到克服。
由于简单工厂模式使用静态方法作为工厂方法,而静态方法无法由子类继承,因此,工厂角色无法形成基于继承的等级结构。这一缺点会在工厂方法模式中得到克服。
 

  好了,关于工厂模式中的简单工厂模式就描述到这,下一节,主要描述工厂模式中的工厂方法。

分享到:
评论

相关推荐

    java设计模式之工厂模式

    java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式...

    java设计模式之工厂方法模式

    工厂方法模式是面向对象设计中的一种经典设计模式,属于创建型模式。它的主要目的是将对象的创建过程封装起来,使得创建过程独立于使用过程。在Java中,工厂方法模式允许我们定义一个创建对象的接口,但让实现这个...

    java 设计模式 mvc模式 单例模式 代理 工厂 简单工厂

    本篇文章将对标题与描述中提到的几个关键Java设计模式进行深入分析。 首先,让我们来看一下MVC模式,这是一种广为接受的架构模式,用于构建用户界面。在MVC模式中,Model层管理数据以及业务逻辑,View层负责将数据...

    工厂模式:简单工厂模式、工厂方法模式、抽象工厂模式

    在给定的资源中,"设计模式交流之工厂模式-shannonxu-2014-10-24.pptx"可能是详细的PPT讲解,涵盖了这些模式的概念、结构、优缺点以及实际应用案例。而"Factory"可能是一个代码示例,展示了工厂模式的具体实现,包括...

    Java 工厂模式 抽象工厂 工厂方法模式

    - `factory2`、`factory3`、`factory1` 这些文件名可能是实现工厂模式的Java源代码,分别代表了不同级别的工厂类,如简单工厂、工厂方法和抽象工厂的实现。通过查看这些源代码,可以学习到如何在实际项目中应用这些...

    设计模式之java工厂模式

    "设计模式之java工厂模式"是关于如何优雅地创建对象的一种经典设计模式,它属于创建者模式类别。创建者模式主要关注对象的创建,而工厂模式则在其中扮演着重要角色,因为它提供了一种抽象的方式来创建对象,从而使...

    Java 工厂设计模式例题

    例题简单的阐述了Java工厂模式的概念,有利于读者更好地了解Java工厂模式

    JAVA设计模式的工厂模式文档和代码

    简单工厂模式通常用于相对简单的对象创建,工厂方法模式则允许子类决定创建哪种产品,而抽象工厂模式关注于一组相关或相互依赖的对象的创建,提供一个创建对象族的接口。 "工厂模式.txt"文本文件可能进一步阐述了...

    JAVA设计模式之工厂模式.pdf

    JAVA设计模式之工厂模式 JAVA设计模式之工厂模式是软件开发中一种常用的设计模式,它专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类。 一、工厂...

    java设计模式-工厂模式

    Java设计模式中的工厂模式是一种创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,当客户端请求创建一个产品对象时,它不会直接创建,而是调用一个工厂对象来完成创建工作。这种模式的核心在于封装了对象...

    设计模式之工厂模式Java实现和类设计图

    本篇将深入探讨工厂模式在Java中的实现以及类设计图的应用。 首先,我们来看简单工厂模式。它是一种静态工厂,通常包含一个静态方法,用于根据输入参数返回所需类型的实例。简单工厂模式的优点在于易于使用,但缺点...

    Java 经典设计模式讲解以及项目实战

    Java 经典设计模式讲解以及项目实战 设计模式简介:主要介绍各种设计模式的概念和运用场景等 设计模式综合运用:主要是笔者在实际工作中运用到的一些设计模式综合运用事例的提炼 Spring设计模式简介:主要是讲述...

    JAVA设计模式之工厂模式

    ### JAVA设计模式之工厂模式 #### 一、工厂模式概述 工厂模式是一种常见的设计模式,主要应用于当系统中存在大量的类实例化需求时。通过工厂模式,我们可以避免直接使用`new`关键字创建对象,而是通过工厂类来创建...

    JAVA设计模式之工厂方法模式

    ### JAVA设计模式之工厂方法模式 #### 一、引言 设计模式是在软件工程领域内广泛应用的一种编程思想,它能够帮助开发者解决常见的软件设计问题,提高代码的可维护性和复用性。面向对象的设计模式更是现代软件开发...

    工厂模式(简单工厂,普通工厂,抽象工厂)代码java

    工厂模式分为三种主要类型:简单工厂模式、普通工厂模式(也称为工厂方法模式)和抽象工厂模式。 1. **简单工厂模式**: - 简单工厂模式中,有一个中心工厂类,它负责根据输入条件(通常是一个参数)来创建具体的...

Global site tag (gtag.js) - Google Analytics