设计模式学习(七):Factory Method工厂模式

简介: 在Template Method模式中,我们在父类中规定处理的流程,在子类中实现具体的处理。如果我们将该模式用于生成实例,它就演变为本章中我们所要学习的Factory Method模式。

一、什么是Factory Method模式


       

在Template Method模式中,我们在父类中规定处理的流程,在子类中实现具体的处理。如果我们将该模式用于生成实例,它就演变为本章中我们所要学习的Factory Method模式。


想先了解Template Method,可以看我的博客:设计模式学习(六):Template Method模板方法模式_玉面大蛟龙的博客


Factory有“工厂”的意思。用Template Method模式来构建生成实例的工厂,这就是Factory Method模式。


在Factory Method模式中,父类决定实例的生成方式,但并不决定所要生成的具体的类,具体的处理全部交给子类负责。这样就可以将生成实例的框架( framework )和实际负责生成实例的类解耦。


用一句话来概括:将实例的生成交给子类。

7ec3e604a0a04e50b00efdb488de73d8.png


二、Factory Method示例代码


       

这段示例程序的作用是制作身份证(ID卡),它其中有5个类(图4-1)。


Product类和Factory类属于framework包。这两个类组成了生成实例的框架。IDCard类和 IDCardFactory类负责实际的加工处理,它们属于idCard包。Main类是用于测试程序行为的类。


之所以将他们分为不同的包,是因为如果我们想再生产其他的产品,比如创建电视机类和电视机工厂类,只需要引入framework包,只编写television包即可。


因此在阅读示例程序时,请注意所阅读的代码属于framework包还是idcard包。


2.1 类之间的关系


先看一下所有的类:

57c17c1f9a8d4fd187bd1561de7dbfdb.png

类图:

7b1e0fbe622d4df09eea16af33ea0755.png

2.2 Product类


framework 包中的Product类是用来表示“产品”的类。在该类中仅声明了use抽象方法。use方法的实现则被交给了Product类的子类负责。


在这个框架中,定义了产品是“任意的可以use的”的东西。

package framework;
public abstract class Product {
    public abstract void use();
}


2.3 Factory类


在framework包中的Factory类中,我们使用了Template Method模式。该类还声明了用于“生成产品”的createProduct抽象方法和用于“注册产品”的registerProduct抽象方法。"生成产品”和“注册产品”的具体处理则被交给了Factory类的子类负责。


在这个框架中,我们定义了工厂是用来“调用create方法生成Product实例”的。而create方法的实现是先调用createProduct生成产品,接着调用registerProduct注册产品。


具体的实现内容根据Factory Method模式适用的场景不同而不同。但是,只要是FactoryMethod模式,在生成实例时就一定会使用到Template Method模式。


在示例程序中,createProduct方法是用于生成实例的方法。不用new关键字来生成实例,而是调用生成实例的专用方法来生成实例,这样就可以防止父类与其他具体类耦合


package framework;
public abstract class Factory {
    public final Product create(String owner) {
        Product p = createProduct(owner);
        registerProduct(p);
        return p;
    }
    protected abstract void registerProduct(Product product);
    protected abstract Product createProduct(String owner);
}


2.4 IDCard类


之前我们已经理解了框架( framework包)的代码。接下来让我们把关注点转移到负责加工处理的这一边(idcard包)。


我们先来编写表示ID卡的类,即IDCard类。为了能够明显地体现出与框架的分离,我们将这个类放在idcard包中。IDCard类是产品 Product类的子类。


需要注意的一点是:我们并没有把IDCard的构造函数声明为public类型,这是想让idcard包外的类无法new出 IDcard 类的实例。这样就可以强迫外部必须通过IDCardFactory来生成IDCard的实例(在Java中,只有同一个包中的类可以访问不带public、protected、private等修饰符的构造函数和方法)。

package idcard;
public class IDCard extends Product {
    private String owner;
    IDCard(String owner) {
        System.out.println("制作" + owner + "的ID卡。");
        this.owner = owner;
    }
    @Override
    public void use() {
        System.out.println("使用" + owner + "的ID卡。");
    }
    public String getOwner() {
        return owner;
    }
}


2.5 IDCardFactory类


package factoryMethod.idcard;
public class IDCardFactory extends Factory {
    //IDCard的各个持有人
    private List owners = new ArrayList();
    //生产产品,即生成IDCard的实例
    protected Product createProduct(String owner) {
        return new IDCard(owner);
    }
    //注册产品,即把各个产品的持有人保存到owners中
    protected void registerProduct(Product product) {
        owners.add(((IDCard)product).getOwner());
    }
    public List getOwners() {
        return owners;
    }
}


2.6 用于测试的Main类


public class Main {
    public static void main(String[] args) {
        Factory factory = new IDCardFactory();
        Product card1 = factory.create("小明");
        Product card2 = factory.create("小红");
        Product card3 = factory.create("小刚");
        card1.use();
        card2.use();
        card3.use();
    }
}


2.7 运行结果

efccf3296d844c37a8049d12e60a5319.png


三、拓展思路的要点



3.1 框架与具体加工


至此,我们分别学习了“框架”与“具体加工”这两方面的内容。它们分别被封装在framework包和idcard包中。


这里,让我们用相同的框架创建出其他的“产品”和“工厂”。例如,我们这次要创建表示电视机的类Televison和表示电视机工厂的类TelevisonFactory。这时,我们只需要引入( import ) framework包就可以编写televison包。


3.2 使用模式与开发人员之间的沟通


不论是我们在之前学习的Template Method模式还是本文中学习的Factory Method模式,在实际工作中使用时,都会让我们感觉到比较困难。这是因为,如果仅阅读一个类的代码,是很难理解这个类的行为的。必须要理解父类中所定义的处理的框架和它里面所使用的抽象方法,然后阅读代码,了解这些抽象方法在子类中的实现才行。


通常,使用设计模式设计类时,必须要向维护这些类的开发人员正确地传达设计这些设计模式的意图。否则,维护人员在修改设计时可能会违背设计者最初的意图。


这时,我们建议在程序注释中和开发文档中记录所使用的设计模式的名称和意图。


四、相关的设计模式



4.1 Template Method模式


Factory Method模式是Template Method的典型应用。在示例程序中,create方法就是模板方法。

设计模式学习(六):Template Method模板方法模式_玉面大蛟龙的博客-CSDN博客


4.2 Singleton模式


在多数情况下我们都可以将Singleton模式用于扮演Creator角色(或是ConcreteCreator角色)的类。这是因为在程序中没有必要存在多个Creator角色(或是ConcreteCreator角色)的实例。不过在示例程序中,我们并没有使用Singleton模式。


4.3 Composite模式


有时可以将Composite模式用于Product角色(或是ConcreteProduct角色 )。


4.4 lterator模式


有时,在 Iterator模式中使用iterator方法生成Iterator的实例时会使用Factory Method模式。


相关文章
|
2月前
|
设计模式 Java
【设计模式】工厂模式(定义 | 特点 | Demo入门讲解)
【设计模式】工厂模式(定义 | 特点 | Demo入门讲解)
67 2
|
3月前
|
设计模式
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
这篇文章详细解释了工厂模式,包括简单工厂、工厂方法和抽象工厂三种类型。每种模式都通过代码示例展示了其应用场景和实现方法,并比较了它们之间的差异。简单工厂模式通过一个工厂类来创建各种产品;工厂方法模式通过定义一个创建对象的接口,由子类决定实例化哪个类;抽象工厂模式提供一个创建相关或依赖对象家族的接口,而不需要明确指定具体类。
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
|
4月前
|
设计模式 Java
Java 设计模式之谜:工厂模式与抽象工厂模式究竟隐藏着怎样的神奇力量?
【8月更文挑战第30天】在Java编程中,设计模式为常见问题提供了高效解决方案。工厂模式与抽象工厂模式是常用的对象创建型设计模式,能显著提升代码的灵活性、可维护性和可扩展性。工厂模式通过定义创建对象的接口让子类决定实例化哪个类;而抽象工厂模式则进一步提供了一个创建一系列相关或相互依赖对象的接口,无需指定具体类。这种方式使得系统更易于扩展和维护。
43 1
|
4月前
|
设计模式 算法 开发者
深入理解工厂模式与策略模式:设计模式的灵活应用
深入理解工厂模式与策略模式:设计模式的灵活应用
|
4月前
|
设计模式 uml
设计模式-------------工厂模式之工厂方法模式(创建型)
工厂方法模式是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而实现类的实例化推迟到子类中进行,提高了系统的灵活性和可扩展性。
|
4月前
|
设计模式 uml C语言
设计模式----------工厂模式之简单工厂模式(创建型)
这篇文章详细介绍了简单工厂模式,包括其定义、应用场景、UML类图、通用代码实现、运行结果、实际应用例子,以及如何通过反射机制实现对象创建,从而提高代码的扩展性和维护性。
设计模式----------工厂模式之简单工厂模式(创建型)
|
4月前
|
设计模式 Java C语言
设计模式-----------工厂模式之抽象工厂模式(创建型)
抽象工厂模式是一种创建型设计模式,它提供了一个接口用于创建一系列相关或相互依赖的对象,而无需指定具体类,从而增强了程序的可扩展性并确保客户端只使用同一产品族的产品。
设计模式-----------工厂模式之抽象工厂模式(创建型)
|
5月前
|
设计模式 C++
C++一分钟之-设计模式:工厂模式与抽象工厂
【7月更文挑战第14天】设计模式是解决软件设计问题的通用方案。工厂模式与抽象工厂模式是创建型模式,用于对象创建而不暴露创建逻辑。工厂模式推迟实例化到子类,但过度使用会增加复杂性。抽象工厂则创建相关对象族,但过度抽象可能造成不必要的复杂度。两者均应按需使用,确保设计灵活性。代码示例展示了C++中如何实现这两种模式。
47 3
|
5月前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
83 1
|
1月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式