设计模式:工厂方法模式(Factory Method)和抽象工厂模式(Abstact Factory)

?在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。 在这些情况,新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。


分类

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

?工厂模式可以分为三类:

  1. 简单工厂模式(Simple Factory)
  2. 工厂方法模式(Factory Method)
  3. 抽象工厂模式(Abstract Factory)

?这三种模式从上到下逐步抽象,并且更具一般性。

?GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。


简单工厂模式

?简单工模式时类的创建模式,又叫做静态工厂方法(static Factory Method)。简单工厂模式是一个工厂对象决定创建出哪一种产品类的实例。它存在的目的很简单:定义一个创建对象的接口。

?组成:

  1. 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。
  2. 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
  3. 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

?举个简单例子:

1 抽象产品角色

public interface IProduct
{
    public void method();
}

2 具体产品角色(可以把方法定义为static的)

public class ProductA implements IProduct
{
    @Override
    public void method()
    {
        System.out.println("I‘m ProductA!");
    }
}

public class ProductB implements IProduct
{
    @Override
    public void method()
    {
        System.out.println("I‘m ProductB!");
    }
}

3 工厂类角色

public class SimpleFactory
{
    public IProduct produce(String type)
    {
        if("A".equals(type))
        {
            return new ProductA();
        }
        else if("B".equals(type))
        {
            return new ProductB();
        }
        else
        {
            System.out.println("请输入正确的类型");
            return null;
        }
    }
}

4 测试类

public class MainTest
{
    public static void main(String args[])
    {
        SimpleFactory factory = new SimpleFactory();
        IProduct product = factory.produce("A");
        product.method();
    }
}

输出:I’m ProductA!

?在Java中java.text.DateFormat就是简单工厂模式的典型案例。

优点:专门定义一个工厂类负责创建其他类的实例,最大的优点在于工厂类中包含了必要的逻辑,根据客户需要的条件动态实例化相关的类。

缺点:当需要增加一种产品时,比如ProductC就需要修改简单工厂类SimpleFactory(增加if-else块),这违背了开闭原则。

TIPS

?其实如果采用反射机制实现简单工厂并没有违背开闭原则。

?利用反射机制,将简单工厂类改成:

public class SimpleFactory
{
    public IProduct produce(Class<? extends IProduct> c) throws Exception
    {
        return (IProduct)Class.forName(c.getName()).newInstance();
//        return (IProduct)c.newInstance();        //或者采用这种方法
    }
}

?测试类:

public class MainTest
{
    public static void main(String args[]) throws Exception
    {
        SimpleFactory factory = new SimpleFactory();
        IProduct product = factory.produce(ProductA.class);
        product.method();
    }
}

?这样当有新的产品时,其实并不需要修改工厂类。《Effective Java(Second Edition)》中明确指出:通常,普通应用程序在运行时不应该以反射方式访问对象。所以本篇文章建立在不采用反射机制的情况下,在下面介绍的工厂方法模式其实也可以改用反射机制实现,博主就不展示了。至于《Effective Java(Second Edition)》为什么不推荐反射机制,可以参考此书的“接口优先于反射机制”这一主题,这里不赘述。


工厂方法模式

?工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。

?来看下它的组成:

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

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

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

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

?举个简单例子:

1 抽象工厂角色

public interface IFactory
{
    public IProduct produce();
}

2 具体工厂角色

public class ConcreteFactoryA implements IFactory
{
    @Override
    public IProduct produce()
    {
        return new ProductA();
    }
}

public class ConcreteFactoryB implements IFactory
{
    @Override
    public IProduct produce()
    {
        return new ProductB();
    }
}

3 抽象产品角色(和简单工厂的一样)

public interface IProduct
{
    public void method();
}

4 具体产品角色(和简单工厂的一样)

public class ProductA implements IProduct
{
    @Override
    public void method()
    {
        System.out.println("I‘m ProductA!");
    }
}

public class ProductB implements IProduct
{
    @Override
    public void method()
    {
        System.out.println("I‘m ProductB!");
    }
}

5 测试代码:

public class MainTest
{
    public static void main(String[] args)
    {
        IFactory factoryA = new ConcreteFactoryA();
        IProduct product1 = factoryA.produce();
        product1.method();
    }
}

输出:I’m ProductA!

工厂方法模式和简单工厂模式在定义上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而不像简单工厂模式, 把核心放在一个实类上。工厂方法模式可以允许很多实的工厂类从抽象工厂类继承下来, 从而可以在实际上成为多个简单工厂模式的综合,从而推广了简单工厂模式。

工厂方法相比于简单工厂模式的优点是增加一个产品,只需要增加一个具体工厂类和具体产品类,没有修改原先的工厂类,符合开闭原则。缺点是客户端的代码会需要修改(简单工厂模式的客户端不需要修改),随着产品的继续增加,所要实现的类的个数也会随之增大。


抽象工厂模式

?在抽象工厂模式中,抽象产品 (AbstractProduct) 可能是一个或多个,从而构成一个或多个产品族(Product Family)。 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。

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

?工厂方法模式:一个抽象产品类,可以派生出多个具体产品类。每个具体工厂类只能创建一个具体产品类的实例。

?抽象工厂模式:多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。一个抽象工厂类可以派生出多个具体工厂类。每个具体工厂类可以创建多个具体产品的实例。

?区别:工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

举个简单例子:

1 抽象产品角色

public interface AbstractProductA
{
    public void produceA();
}
public interface AbstractProductB
{
    public void produceB();
}

2 抽象工厂角色

public interface AbstractFactory
{
    public AbstractProductA CreateProductA();
    public AbstractProductB CreateProductB();
}

3 具体产品角色

public class ProductA1 implements AbstractProductA
{
    @Override
    public void produceA()
    {
        System.out.println("Im ProductA1!");
    }
}
public class ProductA2 implements AbstractProductA
{
    @Override
    public void produceA()
    {
        System.out.println("Im ProductA2!");
    }
}
public class ProductB1 implements AbstractProductB
{
    @Override
    public void produceB()
    {
        System.out.println("Im ProductB1!");
    }
}
public class ProductB2 implements AbstractProductB
{
    @Override
    public void produceB()
    {
        System.out.println("Im ProductB2!");
    }
}

4 具体工厂角色

public class ConcreteFactory1 implements AbstractFactory
{
    @Override
    public AbstractProductA CreateProductA()
    {
        return new ProductA1();
    }

    @Override
    public AbstractProductB CreateProductB()
    {
        return new ProductB1();
    }
}
public class ConcreteFactory2 implements AbstractFactory
{
    @Override
    public AbstractProductA CreateProductA()
    {
        return new ProductA2();
    }

    @Override
    public AbstractProductB CreateProductB()
    {
        return new ProductB2();
    }
}

5 测试代码

public class MainTest
{
    public static void main(String[] args)
    {
        AbstractFactory factory = new ConcreteFactory1();
        AbstractProductA product1 = factory.CreateProductA();
        AbstractProductB product2 = factory.CreateProductB();
        product1.produceA();
        product2.produceB();
    }
}

输出结果:

Im ProductA1!
Im ProductB1!

?抽象工厂的优点:抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

?抽象工厂的缺点:产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

Jdk中的工厂方法

java.lang.Object#toString();

java.lang.Class#newInstance();

java.lang.Class#forName();

java.lang.Boolean#valueOf();

java.lang.Proxy#newProxyInstance();

java.lang.reflect.Array#newInstance();

java.lang.reflect.Constructor#newInstance();


总结

?无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。



参考资料:

1. 《设计模式(一)工厂模式Factory(创建型)

2. 《学习:java设计模式—工厂模式

3. 《23种设计模式(3):抽象工厂模式

4. 《Effective Java(Second Edition)》Joshua Bloch.

5. 《细数JDK里的设计模式

时间: 2024-10-14 16:38:37

设计模式:工厂方法模式(Factory Method)和抽象工厂模式(Abstact Factory)的相关文章

Abstract Factory Design Pattern 抽象工厂设计模式 - 总结

Abstract Factory Design Pattern 就是一般的Factory Design Pattern的进一步设计,增加一个抽象工厂,然后利用这个工厂可以创建不同基类的类. 当我们需要创建更多不同类的时候就可以使用这个设计模式了. 这个设计模式的代码相对会多点,但是其中的思想就是一般Factory Design Pattern,然后集合更多的基类,看起来挺大的一个设计模式,其思想是挺简单的. 其中具体的实现细节当然是可以有多种实现方法的: 1 利用Factory的基类衍生出不同的

工厂模式(Factory)和抽象工厂模式(Abstract Factory)

一.工厂模式(Factory):通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的,工厂方法让类的实例化推迟到子类 (1)涉及角色:抽象产品,具体产品,抽象创建者,具体创建者.                (2)实例:    抽象产品类 1 public abstract class ProductNoodle { 2 public abstract String description(); 3 } 具体产品类 1 public class ConcreteNoodleA e

设计模式那点事读书笔记(2)----抽象工厂模式

抽象工厂模式: 此模式提供了一个接口,用于创建相关或者依赖对象的家族,而不需要指定具体实现类. 解决什么问题: 抽象工厂模式允许客户在使用抽象接口来创建一组相关的产品,客户类和工厂类分开,客户需要任何产品的时候,只需要向工厂请求即可,客户无须修改就可以获得新产品.从而实现客户从具体的产品中解耦. UML: 代码结构: 代码: 定义抽象产品: package com.demo.factory.model; /** * 抽象产品 */ public abstract class AbstractBa

面向程序员的设计模式 ——GoF《设计模式》读书总结(壹)抽象工厂&amp;生成器

第一部分:创建型模式 创建型模式抽象了实例化过程.它们帮助一个系统独立于如何创建.组合和表示它的那些对象.(把一些小的对象组装成大对象,这个工作由专门的类对象来做) 一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象. 随着系统演化得越来越依赖于对象复合而不是类继承,创建型模式变得更为重要.因为系统定义一个较小的行为集,这些行为可以被组合成任意数目的更复杂的行为. (把行为分散在各类中,用对象组合的方式,根据需要组合成大类) 这些创建型模式有两个特点: 1.它

设计模式系列一创建型之(抽象工厂模式)

1.抽象工厂简介 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作:同时由于需求的变化,往往存在着更多系列对象的创建工作. 如何应对这种变化? 如何绕过常规的对象的创建方法(new)? 如何来避免客户程序和这种“多系列具体对象创建工作”的紧耦合? 然而抽象工厂便可以很好地解决这个问题! 2.意图 提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类. 3.适用性 一个系统要独立与它的产品创建.组合和表示时 一个系统要由多个产品系列中的一个来配置时 当你要强调一系列相关的产

2,抽象工厂模式(Abstract Factory Pattern) 抽象工厂可以一下生产一个产品族(里面有很多产品组成)

备注    工厂模式:要么生产香蕉.要么生产苹果.要么生产西红柿:但是不能同时生产一个产品组. 抽象工厂:能同时生产一个产品族.===>抽象工厂存在原因 解释 :    具体工厂在开闭原则下,                能生产香蕉/苹果/梨子;  (产品等级结构) 抽象工厂:在开闭原则下,               能生产:南方香蕉/苹果/梨子 (产品族)  北方香蕉/苹果/梨子 重要区别:              工厂模式只能生产一个产品.(要么香蕉.要么苹果)            

终极版:由简单工厂模式,升级到抽象工厂模式(用到反射)

前面两个已经学习简单三层到简单工厂模式的变化,但是简单工厂模式还是有个缺点,就是简单工厂中集合了所有的实例的创建.也不是很好. 现在想到使用抽象工厂的方式来实现这个: 我们在程序集中加上下面的代码: <appSettings> <!--命名空间--> <add key="DALNameSpace" value="DAL"/> <!--程序集--> <add key="DALAssembly"

java进阶之工厂模式(二)抽象工厂模式

public interface KitchenFactory{ //抽象工厂 public Food getFood(); 抽象方法 public TableWare getTableWare(); } public interface Food{ //抽象食物 public String getFoodName(); } public interface TableWare{ public String getToolName(); //抽象餐具 } public class AKitche

设计模式之_简单工厂模式、工厂方法模式、抽象工厂模式 、策略模式、策略与工厂的区别(转)

一.前言 话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰).Bmw(宝马).Audi(奥迪)),还雇了司机为他开车.不过,爆发户坐车时总是这样:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上 Audi后他说“开奥迪车!”.你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的 幸运的是这种有病的现象在OO语言中可以避免了.下面以Java语言为基础来引入我们本文的主题:工厂模式! 二.简介