23种常用设计模式-工厂方法(Factory Method)模式

253次阅读
没有评论

共计 4336 个字符,预计需要花费 11 分钟才能阅读完成。

内容目录

工厂方法模式

概述

 工厂方法模式与模板方法模式类似,只不过模板方法关注的是方法执行,而工厂方法模式关注的对象的创建。工厂方法的目的是使得创建对象和使用对象是分离的,并且客户端总是引用抽象工厂和抽象产品

类型

 工厂方法模式属于创建型模式。

介绍

  • 目的:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类。
  • 主要解决:主要解决接口选择的问题。
  • 使用场景:在不同的条件下需要创建不同的实例。
  • 解决方案:定义一个抽象接口用于创建抽象产品,至于如何创建,由子类进行实现。
  • 注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

示例代码

 这里我们以生产不同类型的手机为例。

需求分析

 首先,我们可以假设每个手机的生产流程是一致的,即:创建手机实例makePhone(),登记手机基本信息registerPhone(),因此,我们可以将整个生产过程抽象出来,将其作为一个手机工厂,即:PhoneFactory,而对应的抽象产品就是Phone

 其次,对于不同的手机其具体的生产过程会有所区别的,但流程均遵循上述提到的两个过程:makePhone()registerPhone()。假设我们要生产ApplePhone,那么就有一个对应的ApplePhoneFactory

 最后,我们让ApplePhoneFactory和ApplePhone分别实现PhoneFactory和Phone即可。

PhoneFactory类

package factoryMethod;

public abstract class PhoneFactory {
    abstract Phone makePhone(String model);
    abstract void registerPhone(Phone phone);
    // 这一步类似于模板方法,无论哪款手机,我们的创建过程都是创建手机实例,然后在登记该手机的基本信息
    Phone create(String model){
        Phone phone = makePhone(model);
        registerPhone(phone);
        return phone;
    }
}

Phone类

package factoryMethod;

public abstract class Phone {
    // 无论那种型号的手机,都有一个创建完成时打印创建成功的信息
    abstract void make();
}

ApplePhoneFactory类

package factoryMethod;

import java.util.ArrayList;
import java.util.List;

public class ApplePhoneFactory extends PhoneFactory{
    // 用于存放注册过的手机
    private final List<ApplePhone> phones = new ArrayList<>();
    @Override
    Phone makePhone(String model) {
        ApplePhone applePhone = new ApplePhone(model);
        // 创建完成后,这里会打印创建成功的提示信息
        applePhone.make();
        return applePhone;
    }

    @Override
    void registerPhone(Phone phone) {
        // 记录过手机基本信息的手机实例 会存放在一个集合中
        phones.add((ApplePhone) phone);
        System.out.println(((ApplePhone) phone).getModel() + " is registered!");
    }
}

ApplePhone类

package factoryMethod;

public class ApplePhone extends Phone{
    // 手机的基本信息,这里只给出一个型号的信息
    private String model;
    public ApplePhone(String model){
        this.model = model;
    }

    public String getModel(){
        return this.model;
    }

    @Override
    void make() {
        System.out.println("phone model (" + model + ") is created");
    }
}

 接着我们写一下测试代码跑一跑吧!

package factoryMethod;

import org.junit.Test;

public class FactoryMethodTest {
    @Test
    public void factoryMethodTest(){
        PhoneFactory applePhoneFactory = new ApplePhoneFactory();
        Phone phone10 = applePhoneFactory.create("iPhone 10");
        Phone phone11 = applePhoneFactory.create("iPhone 11");
    }
}

 控制台的日志如下:

phone model (iPhone 10) is created
iPhone 10 is registered!
phone model (iPhone 11) is created
iPhone 11 is registered!

 可以看到我们创建对象是通过对应的工厂得到的,也就是创建过程不再由我们开发者控制,而是交给工厂。我们需要什么对象,就通过工厂获得,至于具体的创建过程,我们并不在乎。那么,如果现在又需要创建小米型号的手机,我们该怎么办呢?很简单,创建XiaoMiPhoneFactoryXiaoMiPhone分别实现PhoneFactoryPhone即可,代码如下:

XiaoMiPhone类

package factoryMethod;

public class XiaoMiPhone extends Phone{
    private String model;
    public XiaoMiPhone(String model){
        this.model = model;
    }
    public String getModel(){
        return this.model;
    }
    @Override
    void make() {
        System.out.println("phone model ("+model+") is created!");
    }
}

XiaoMiPhoneFactory类

package factoryMethod;

import java.util.ArrayList;
import java.util.List;

public class XiaoMiPhoneFactory extends PhoneFactory{

    private final List<XiaoMiPhone> phones = new ArrayList<>();
    @Override
    Phone makePhone(String model) {
        XiaoMiPhone xiaoMiPhone = new XiaoMiPhone(model);
        xiaoMiPhone.make();
        return xiaoMiPhone;
    }

    @Override
    void registerPhone(Phone phone) {
        phones.add((XiaoMiPhone) phone);
        System.out.println(((XiaoMiPhone)phone).getModel() + " is registered!");
    }
}

 同样的,我们可以通过测试代码跑一跑效果:

package factoryMethod;

import org.junit.Test;

public class FactoryMethodTest {
    @Test
    public void factoryMethodTest(){
        PhoneFactory applePhoneFactory = new ApplePhoneFactory();
        PhoneFactory xiaoMiPhoneFactory = new XiaoMiPhoneFactory();
        // 生产两部iPhone手机
        Phone phone10 = applePhoneFactory.create("iPhone 10");
        Phone phone11 = applePhoneFactory.create("iPhone 11");
        // 生产一部XiaoMi手机
        Phone phone = xiaoMiPhoneFactory.create("xiaomi 13");
    }
}

 控制台日志如下:

phone model (iPhone 10) is created
iPhone 10 is registered!
phone model (iPhone 11) is created
iPhone 11 is registered!
phone model (xiaomi 13) is created!
xiaomi 13 is registered!

类图

23种常用设计模式-工厂方法(Factory Method)模式

工厂方法中的角色

  • Product: 即工厂生产出来的产品,是一个抽象类,它定义了在工厂方法模式中生产的那些实例所持有的接口,但具体的处理则由子类ConcreteProduct角色决定。在上述示例中,Phone扮演着此角色。
  • Creator: 创建者,也即工厂,它是负责生成Product角色的抽象类,但具体的生产过程则由子类ConcreteCreator角色决定,在上述代码中,PhoneFactory扮演着这一角色。
  • ConcreteProduct: 它决定了工厂生产出的具体产品,在上述代码中,ApplePhoneXiaoMiPhone扮演着这一角色。
  • ConcreteCreator: 它负责生产具体的产品,上述代码中,ApplePhoneFactoryXiaoMiPhoneFactory扮演着这一角色。

23种常用设计模式-工厂方法(Factory Method)模式

Creator角色对于实际负责生成实例的ConcreteCreator角色是一无所知的,它唯一知道的就是:只要调用Product角色和生成实例的方法,就可以生产出Product的实例。在上述代码中,create方法就是用于创建对象的方法。不用new关键字来创建实例对象,而是调用创建实例对象的方法来创建对象,这样就可以防止父类与其它具体类耦合。

其它

 作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

正文完
 
PG Thinker
版权声明:本站原创文章,由 PG Thinker 2023-10-13发表,共计4336字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
热评文章
Rust中所有权与借用规则概述

Rust中所有权与借用规则概述

在GC与手动管理内存之间,Rust选择了第三种:所有权机制...