设计模式学习(七):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模式。


相关文章
|
7天前
|
设计模式 Java 容器
【设计模式】JAVA Design Patterns——Async Method Invocation(异步方法调用模式)
【设计模式】JAVA Design Patterns——Async Method Invocation(异步方法调用模式)
|
7天前
|
设计模式 Java
【设计模式】JAVA Design Patterns——Abstract Factory(抽象工厂模式)
【设计模式】JAVA Design Patterns——Abstract Factory(抽象工厂模式)
|
12天前
|
设计模式 Java
Java一分钟之-设计模式:工厂模式与抽象工厂模式
【5月更文挑战第17天】本文探讨了软件工程中的两种创建型设计模式——工厂模式和抽象工厂模式。工厂模式提供了一个创建对象的接口,延迟实例化到子类决定。过度使用或违反单一职责原则可能导致问题。代码示例展示了如何创建形状的工厂。抽象工厂模式则用于创建一系列相关对象,而不指定具体类,但添加新产品可能需修改现有工厂。代码示例展示了创建颜色和形状的工厂。根据需求选择模式,注意灵活性和耦合度。理解并恰当运用这些模式能提升代码质量。
26 2
|
4天前
|
设计模式
设计模式之工厂 Factory
设计模式之工厂 Factory
9 1
|
6天前
|
设计模式 安全 Java
【JAVA学习之路 | 基础篇】单例设计模式
【JAVA学习之路 | 基础篇】单例设计模式
|
12天前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
14天前
|
设计模式 安全 Java
【设计模式学习】单例模式和工厂模式
【设计模式学习】单例模式和工厂模式
|
14天前
|
设计模式 Java
Java 设计模式:工厂模式与抽象工厂模式的解析与应用
【4月更文挑战第27天】设计模式是软件开发中用于解决常见问题的典型解决方案。在 Java 中,工厂模式和抽象工厂模式是创建型模式中非常核心的模式,它们主要用于对象的创建,有助于增加程序的灵活性和扩展性。本博客将详细介绍这两种模式的概念、区别以及如何在实际项目中应用这些模式。
17 1
|
14天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
14天前
|
设计模式 算法 程序员
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践