设计模式——工厂方法模式

设计模式——工厂方法模式

一、   何为设计模式

在面向对象的程序设计原则中,总是希望尽量的避免重复设计。有经验的设计者知道,不是所有的问题都要从头解决,他们更希望从以前的解决方案找到解决该问题的方法,复用以往成功的设计模式,使用者就不需要重新去发现它们,而能够立即使用现有的设计模式,这极大的提高了程序开发的速度和质量。因此,熟悉以往那些成熟的设计模式,也是一个有经验的开发者所应具备的技能。

每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动。

根据目的准则的分类,设计模式可分为创建型,结构型和行为型三类。创建型模式与对象的创建有关;结构型模式处理类或对象的组合;行为型模式对类或对象怎样交互和怎样分配职责进行描述。本文先介绍创建型的设计模式。

二、   工厂方法模式

在程序设计中,有时候客户端并不需要知道所使用的对象的创建过程,或者对使用哪一个具体的对象并不确定,这时候就可以使用工厂方法来解决这个问题。定义一个用于创建对象的接口,让子类去决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。这样客户端就只需要了解这个接口即可。

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

到这里,我想大家对工厂方法也应该有了一定的了解了吧,为了便于对工厂方法模式的深入了解,下面我们先看看简单的工厂模式是如何实现的。

 

2.1简单的工厂模式

    简单工厂模式又称静态工厂方法模式。这个模式很简单。它就是为了定义一个用于创建对象的接口。

    简单工厂方法的组成:

a) 工厂角色:这是本模式的核心,含有一定的逻辑判断以确定实例化具体对象。

b)  抽象产品角色:它是具体产品继承的父类或者是实现的接口。在 java 中一般有抽象类或者接口来实现。

c)  具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在 java 中由具体的类

来实现

各角色之间的关系图:

 

那么简单的工厂模式是如何使用的呢,请看下面的具体代码:

抽象产品类:

Public interface Ball (){

                Public void play();

}

具体产品类:

Public class Basketball implements Ball(){

                Public void play(){

System.out.println( 打篮球 );

}

}

Public class Football implements Ball(){

    Public void play(){

System.out.println( 踢足球 );

}

}

具体工厂类:

Public class Factory(){

    //静态方法,工厂方法的返回类型必须为产品

    Public static Ball getBall(标识){

    If(标识 == basketball){

    Return new Basketball();

}

Else If(标识 == football){

                Return new Football();

}

……

}

客户端:

Public class player (){

    public static void main(String[] args){

        Factory factory = new Factory();

        Ball ball = factory.getBall(标识);

        Ball.play();

}

}

    以上就是简单工厂模式的实现过程了,怎么样,看起来很简单吧,虽然解决了对象实例化一实际使用分离的问题,但是这个模式是不是已经很完美了呢?

    从面相对象编程的开闭原则来分析,如果这个程序以后要进行扩展即假如有新产品的加入时,对于产品部分而言,只需要添加新的具体产品类去实现产品接口即可,这是符合开闭原则的。但是从工厂部分来看,由于其工厂方法实现是通过一定的逻辑判断,静态装载具体对象的,所以当有新产品加入时,工厂部分的代码也需做出相应的修改,这显然是违背了开闭原则的,这也就是简单工厂模式存在的缺陷。

    那么这个问题要如何解决呢,于是工厂方法模式就产生了,它是简单工厂模式的改良版。

2.2工厂方法模式

    工厂方法模式相比简单的工厂模式而言,就是多了一个抽象工厂角色,以此来解决上面所遇到的问题,还是老样子,通过组成和代码对该模式就行解析。

    以下是工厂方法的组成:

a)  抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java 中它由抽象类或者接口来实现。

b)  具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体

产品的对象。

c)  抽象产品角色:它是具体产品继承的父类或者是实现的接口。在 java 中一般有抽象类

或者接口来实现。

d)  具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在 java 中由具体的类

来实现。

各角色之间的关系图:

 

为了便于理解工厂方法中,各个角色之间是如何协作的,请看以下具体代码进行示例:

抽象产品类:

Public interface Ball (){

    Public void play();

}

具体产品类:

Public class Basketball implements Ball(){

    Public void play(){

System.out.println( 打篮球 );

}

}

Public class Football implements Ball(){

    Public void play(){

System.out.println( 踢足球 );

}

}

抽象工厂类:

Public interface Factory (){

    //工厂方法返回类型必须为产品

    Public Ball getBall();

}

具体工厂类:

Public class BasketballFactory(标识){

    Public Ball getBall(){

Return new Basketball();

}

 

}

Public class FootballFactory(){

    Public Ball getBall(){

Return new Football();

}

}

客户端:

Public class player (){

    public static void main(String[] args){

        Factory basketballFactory = new BasketballFactory();

        Ball ball = basketballFactory.getBall();

        Ball.play();

 

}

}

结果:打篮球

分析:

由以上代码可知,客户端不需要去了解对象的创建过程,也不需要确定所需的对象是具体的哪一个,使得客户程序中仅仅处理抽象产品角色提供的接口,也就是该设计模式把我们需要将创建实例的工作与使用实例的工作分开,这是该模式的好处。

在工厂方法模式中,要么将判断逻辑(具体创建那个对象)留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样)。如果有新的产品加入,只需修改具体产品类的角色,所以对产品部分来说,它是符合开闭原则的。但是当产品对象创建条件的改变必然会引起工厂角色的修改。所以,这个模式也不能完全避免代码改动的。

使用工厂方法要注意几个角色,首先你要定义产品接口,如上面的Ball,产品接口下有Ball 接口的实现类,其次要有一个factory 类,用来生成产品,进一步稍微复杂一点,就是在工厂类上进行拓展,工厂类也有继承它的实现类concreteFactory了。

 

2.3另种解决方式——通过动态装载对简单工厂模式进行改良

    我们知道,造成简单工厂模式问题的罪魁祸首就是工厂方法中的逻辑判断和静态装载对象,因此,我们可以用一个更简单的方法去改良简单工厂模式,来达到与工厂方法模式一样效果的设计模式。

    该模式的角色组成及其关系和简单工厂模式一样,唯一不同的是对工厂角色中,工厂方法的改进,也就是用动态转载去替换其逻辑判断与静态转载过程。

    具体请看工厂类的代码:

 

具体工厂类:

Public class Factory() throw exception{

    //静态方法,工厂方法的返回类型必须为产品

    Public static Ball getBall(标识){

    //动态,改进,当有新产品添加进来时,只需添加标识,根据标识,从工厂创建具体对象

Class c = class.forName(标识);

Object obj = c.newInstance();

Ball ball = (Ball)obj;

Return ball;

}

    现在我们来分析一下动态转载问什么能解决这个问题,如果大家对静态转载和动态装载对象有所了解的话,那么这个原理就显而易见了。静态装载在程序编译时就必须确定具体对象的存在,也就是定死了,所以当有新产品添加时,工厂方法也必须添加相应的逻辑判断和代码。但是对于动态装载而言,程序编译时是不会确定具体对象的,也就是说,它是在程序运行时通过标识去查找确定所需的类的,这样就给工厂方法带来了很多的灵活性,当程序需要扩展时,就只需要去添加具体产品部分,而不需要去修改工厂部分的代码了。

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值