设计模式是为解决生活中的问题而诞生的,也就是说我们可以通过生活中的问题来解释各种各样的模式,是前人对代码开发经验的总结。

工厂模式分为简单工厂、工厂方法、抽象工厂。我们可以通过使用生活的例子来解释它们的作用

1、简单工厂可以看做一些小作坊模式,生产的产品由客户选择(简单工厂if、else或者case语句较多)

具体结构有:

工厂:实现产品的内部逻辑,由外界调用。

抽象产品:所有产品的共有方法,由产品实现。

产品:简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。

 

工厂的产品

package des.factory;

public interface Milk {
    /**
     * 获取一个标准的产品
     * @return
     */
    String getName(String name);
}

抽象产品

package des.factory;

public class YiLi implements Milk{
    @Override
    public String getName(String name) {
        return "YILI";
    }
}

工厂

package des.factory.simple;

import des.factory.Milk;
import des.factory.YiLi;

public class SimpleFactory {
    public Milk getName(String name){
        if(name.equals("YiLi")){
            return  new YiLi();
        }
        return null;
    }
}

简单工厂模式的优缺点及其适用环境

优点:

(1)工厂类中已经包含必要的逻辑判断,客户无需要创建产品类

(2)客户不需要知道具体的产品类,只需要知道具体的几个参数即可

(3)可以通过引入xml方式来产生和创建产品

缺点:

(1)工厂类中集齐了所有的逻辑判断职责过重,一旦出现异常,则会崩溃

(2)使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
(3)系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂

适用环境:

(1)工厂类负责创建对的对象比较少,因为不会造成工厂方法中的业务逻辑过于复杂

(2)客户端只知道传入工厂类的参数,对如何创建对象不关心

 

2、工厂方法可以看做一条流水线进行生产,只能生产一个产品

具体的结构:

抽象工厂:声明抽象工厂的方法,用于生产一件产品。

具体工厂:实现产品的内部逻辑,由外界调用。

抽象产品:所有产品的共有方法,由产品实现。

产品:简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。

代码在简单工厂的抽象产品,具体产品类的基础上添加抽象工厂、具体工厂

抽象工厂

package des.factory.func;

import des.factory.Milk;

public interface factory {
    Milk getMilk();
}

具体工厂

package des.factory.func;

import des.factory.Milk;
import des.factory.YiLi;

public class YiLiFactory implements factory{
    @Override
    public Milk getMilk() {
        return new YiLi();
    }
}

工厂方法模式的优缺点及其适用环境

优点:

(1)更符合开-闭原则 
新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可

(2)符合单一职责原则 
每个具体工厂类只负责创建对应的产品

(3)不使用静态工厂方法,可以形成基于继承的等级结构。

缺点:

(1)添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;

(2)由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

(3)虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;

(4)一个具体工厂只能创建一种具体产品

适用环境:

(1)当一个类不知道它所需要的对象的类时 
在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可;

(2)当一个类希望通过其子类来指定创建对象时 
在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

(3)将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

 

3抽象工厂可以看做一个大规模的工厂,标准化批量的生产多种商品

抽象工厂:声明抽象工厂的方法,用于生产多件产品。

具体工厂:实现产品的内部逻辑,由外界调用。

抽象产品:所有产品的共有方法,由产品实现。

产品:简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。

在工厂方法的抽象产品,具体产品的基础上,增加抽象工厂,具体工厂

抽象工厂

package des.factory.abstrac;

import des.factory.Milk;

public abstract class AbstractFactory {
    public abstract Milk getYiLi();
}

具体工厂

package des.factory.abstrac;

import des.factory.Milk;
import des.factory.YiLi;

public class MilkFactory extends AbstractFactory{

    @Override
    public Milk getYiLi() {
        return new YiLi();
    }
}

抽象工厂模式的优缺点及其适用环境

优点

(1)具体产品在应用层代码隔离,无须关心创建细节
(2)将一系列的产品族统一到一起创建

缺点

(1)规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
(2)增加了系统的抽象性和理解难度

适用环境

1、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
2、强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码
3、提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现