4. 工厂方法模式

工厂方法模式

文章目录

  • 工厂方法模式
      • 1. 意图
      • 2. 概述
      • 3. 结构图
      • 4. java代码实现
      • 5. 优缺点
      • 6. 使用场景
      • 7. 与其他模式的关系
      • 8. Java应用

1. 意图

简单工厂模式通过所传入的不同来创建不同产品,必须要修改工厂类源代码,违反开闭原则,需要实现增加新产品而不影响源代码

2. 概述

工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式。

3. 结构图

4. 工厂方法模式_第1张图片

● Product(抽象产品):它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。
● ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。

**注意, 并不一定每次调用工厂方法都会创建新的实例。 工厂方法也可以返回缓存、 对象池或其他来源的已有对象。**

● Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。
● ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。

4. java代码实现

/**
 *抽象产品类
 **/
abstract class Product{
    //公共方法
    public void sameMethod(){
        
    }
    //声明抽象方法
    public abstract void diffMethod(); 
}
/**
*具体产品类A
**/
class ConcreateProductA extends product{
    @Overrible
    public void diffMethod(){
		...
    }
}
/**
*具体产品类B
**/
class ConcreateProductB extends product{
    @Overrible
    public void diffMethod(){
		...
    }
}
/**
*抽象产品工厂类
**/
interface Factory{
    Product createProduct();
}
/**
*具体工厂类A
**/
class ConcreateProductAFactory implements Factory{
    public Product createProduct(){
        return new ConcreateProductA();
    }
}
/**
*具体工厂类B
**/
class ConcreateProductBFactory implements Factory{
    public Product createProduct(){
        return new ConcreateProductB();
    }
}
/**
*客户端调用
**/
class Client{
    public static void main(String []args){
		Factory factory = new ConcreateProductAFactory();
        Product product = factory.createProduct();
    }
}

5. 优缺点

优点

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

缺点

  • 在添加新产品时,需要编写新的具体产品类、具体工厂类,增加类个数,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

6. 使用场景

  • 客户端不知道它所需要的对象的类。在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建,可将具体工厂类的类名存储在配置文件或数据库中。
  • 抽象工厂类通过其子类来指定创建哪个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
  • 当你在编写代码的过程中, 如果无法预知对象确切类别及其依赖关系时, 可使用工厂方法。
  • 如果你希望用户能扩展你软件库或框架的内部组件, 可使用工厂方法。
  • 如果你希望复用现有对象来节省系统资源, 而不是每次都重新创建对象, 可使用工厂方法。

7. 与其他模式的关系

  • 在许多设计工作的初期都会使用工厂方法模式(较为简单, 而且可以更方便地通过子类进行定制), 随后演化为使用抽象工厂模式、 原型模式生成器模式(更灵活但更加复杂)。
  • 抽象工厂模式通常基于一组工厂方法, 但你也可以使用原型模式来生成这些类的方法。
  • 你可以同时使用工厂方法迭代器模式来让子类集合返回不同类型的迭代器, 并使得迭代器与集合相匹配。
  • 原型并不基于继承, 因此没有继承的缺点。 另一方面, 原型需要对被复制对象进行复杂的初始化。工厂方法基于继承, 但是它不需要初始化步骤。
  • 工厂方法模板方法模式的一种特殊形式。 同时, 工厂方法可以作为一个大型模板方法中的一个步骤。

8. Java应用

核心 Java 程序库中有该模式的应用:

  • java.util.Calendar#getInstance()
  • java.util.ResourceBundle#getBundle()
  • java.text.NumberFormat#getInstance()
  • java.nio.charset.Charset#forName()
  • java.net.URLStreamHandlerFactory#createURLStreamHandler(String) (根据协议返回不同的单例对象)
  • java.util.EnumSet#of()
  • javax.xml.bind.JAXBContext#createMarshaller() 及其他类似的方法。

t#createMarshaller()`](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller–) 及其他类似的方法。

识别方法: 工厂方法可通过构建方法来识别, 它会创建具体类的对象, 但以抽象类型或接口的形式返回这些对象。

你可能感兴趣的:(设计模式,java)