工厂方法模式

标签: 设计模式  工厂方法模式

定义

工厂方法(FactoryMethod)模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
工厂方法模式是一种创建型设计模式,其在父类中提供一个创建对象的接口,允许子类决定实例化对象的类型。

结构

在这里插入图片描述

  1. 产品(Product)将会对接口进行声明。 对于所有由创建者及其子类构建的对象, 这些接口都是通用的。
  2. 具体产品 (Concrete Products) 是产品接口的不同实现。
  3. 创建者 (Creator) 类声明返回产品对象的工厂方法。 该方法的返回对象类型必须与产品接口相匹配。注意, 尽管它的名字是创建者, 但他最主要的职责并不是创建产品。
  4. 具体创建者 (Concrete Creators) 将会重写基础工厂方法, 使其返回不同类型的产品。注意, 并不一定每次调用工厂方法都会创建新的实例。 工厂方法也可以返回缓存、 对象池或其他来源的已有对象。

问题

假设正在开发一款物流管理应用,最初只能处理卡车运输,因此大部分代码都在位于名为卡车的类中。之后对该应用进行扩充,添加轮船类运输方式,这时不得不修改全部代码。如果以后需要在程序中支持另一种运输方式,很可能需要再次对这些代码进行大幅修改。

解决方案

工厂模式使用工厂方法代替对象构造函数的直接调用。
在这里插入图片描述
调用工厂方法的代码 (通常被称为客户端代码) 无需了解不同子类返回实际对象之间的差别。客户端将所有产品视为抽象的运输 。 客户端知道所有运输对象都提供交付方法, 但是并不关心其具体实现方式。具体代码实现如下:

public class Transportations {
    public static void deliver(TransportationFactory factory){
        Transportation t = factory.getTransportation();
        t.deliver();
    }

    public static void main(String[] args){
        deliver(new TruckFactory());
        deliver(new ShipFactory());
    }
}

interface Transportation{
    void deliver();
}

interface TransportationFactory{
    Transportation getTransportation();
}

class Truck implements Transportation{
    public void deliver(){
        System.out.println("delivered by truck!");
    }
}
class TruckFactory implements TransportationFactory{
    public Transportation getTransportation(){
        return new Truck();
    }
}

class Ship implements Transportation{
    public void deliver(){
        System.out.println("delivered by ship!");
    }
}
class ShipFactory implements TransportationFactory{
    public Transportation getTransportation(){
        return new Ship();
    }
}

适用场合

  1. 当你在编写代码的过程中,如果无法预知对象确切类别及其依赖关系时,可使用工厂方法。
  2. 如果你希望用户能扩展你软件库或框架的内部组件,可使用工厂方法。
  3. 如果你希望复用现有对象来节省系统资源,而不是每次都重新创建对象,可使用工厂方法。

实现方式

  1. 让所有产品都遵循同一接口。 该接口必须声明对所有产品都有意义的方法。如上例中:
interface Transportation{
    void deliver();
}
  1. 在创建类中添加一个空的工厂方法。 该方法的返回类型必须遵循通用的产品接口。
interface TransportationFactory{
    Transportation getTransportation();
}
  1. 在创建者代码中找到对于产品构造函数的所有引用。 将它们依次替换为对于工厂方法的调用, 同时将创建产品的代码移入工厂方法。 你可能需要在工厂方法中添加临时参数来控制返回的产品类型。

  2. 现在, 为工厂方法中的每种产品编写一个创建者子类, 然后在子类中重写工厂方法, 并将基本方法中的相关创建代码移动到工厂方法中。

class Truck implements Transportation{
    public void deliver(){
        System.out.println("delivered by truck!");
    }
}
class TruckFactory implements TransportationFactory{
    public Transportation getTransportation(){
        return new Truck();
    }
}
  1. 如果应用中的产品类型太多, 那么为每个产品创建子类并无太大必要, 这时你也可以在子类中复用基类中的控制参数。
  2. 如果代码经过上述移动后, 基础工厂方法中已经没有任何代码, 你可以将其转变为抽象类或接口。 如果基础工厂方法中还有其他语句, 你可以将其设置为该方法的默认行为。

优缺点

优点:

  • 避免创建者和具体产品的耦合
  • 单一权责原则。你可以将产品创建代码放在程序的单一位置,从而使得代码更容易维护。
  • 开闭原则。无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。

缺点:

应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。

版权声明:本文为weixin_43116322原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43116322/article/details/103068838