设计模式之工厂方法

简介: 设计模式之工厂方法

一、介绍

工厂模式(Factory Pattern)是最常使用的设计模式之一,属于创建型设计模式。在该设计模式中,我们不再使用new来实例化对象,而是通过工厂对象来获取指定的对象实例,其中对象的实例化过程是在工厂中完成的。换句话说,就是将对象的实例化过程从 调用方控制 改变成 工厂控制

说到这里,我愣了一下,这不就是控制反转(IOC)嘛?

大家回忆一下spring框架的IOC容器:spring的IOC容器主要使用的设计模式之一就是工厂模式,它将我们对对象的控制权转移给了BeanFactoryBeanFactory把实例化的对象放在单例池(即容器)中,当我们需要从spring中获取一个对象时,spring直接从该容器中获取对应的实例并返回给我们。

因此,我们使用工厂方法的目的是通过工厂提供一种统一的接口来创建不同类型的对象,将对象的创建过程与对象的使用过程分离,因为对象的创建过程是由工厂负责的,工厂只需要提供一个获取已创建的对象实例的方法。

二、基本组件

在我们使用工厂方法时,一般需要以下组件:

  • 工厂抽象。接口或抽象类,定义了工厂的行为。
  • 工厂实现类。对工厂的行为提供了具体实现。不同的工厂实现类用于创建不同的产品实现类。
  • 产品抽象。作为父类或接口,规定了一类具有相同行为的产品。
  • 产品实现类。产品抽象类的具体实现。

一般来讲,从工厂中获取的对象类型为抽象类型,其具体类型由工厂方法决定。

如下图所示

UML图1.jpg

三、案例应用

我们举一个例子,有一个自行车公司(BicycleFactory),主要业务为生产自行车(Bicycle),该公司有两个工厂,专门生产哈罗单车(HaLuoBicycle)的工厂(HaLuoBicycleFactory) 和 专门生产美团单车(MeiTuanBicycle)的工厂(MeiTuanBicycleFactory)

其中,自行车公司(BicycleFactory)即为工厂抽象,提供create()方法生产自行车。哈罗单车工厂(HaLuoBicycleFactory) 和 美团单车工厂(MeiTuanBicycleFactory)作为工厂实现类。自行车(Bicycle)为产品抽象。哈罗单车(HaLuoBicycle) 和 美团单车(MeiTuanBicycle) 作为产品实现类。

如下图所示

UML图2.jpg

1. 代码演示

下面我们通过代码模拟工厂模式的实现

  • 自行车公司(BicycleFactory)

    public interface BicycleFactory {
         
         
    
        /**
         * 生产单车
         * @return 抽象的单车
         */
        public Bicycle create();
    }
    
  • 哈罗单车工厂(HaLuoBicycleFactory)

    public class HaLuoBicycleFactory implements BicycleFactory {
         
         
    
        /**
         * 生产哈罗单车
         * @return 哈罗单车
         */
        @Override
        public Bicycle create() {
         
         
            return new HaLuoBicycle();
        }
    }
    
  • 美团单车工厂(MeiTuanBicycleFactory)

    public class MeiTuanBicycleFactory implements BicycleFactory {
         
         
    
        /**
         * 生产美团单车
         * @return 美团单车
         */
        @Override
        public Bicycle create() {
         
         
            return new MeiTuanBicycle();
        }
    }
    
  • 自行车(Bicycle)

    public interface Bicycle {
         
         
        /**
         * 获取颜色
         * @return 颜色
         */
        String getColor();
    
        /**
         * 获取品牌
         * @return 品牌
         */
        String getBrand();
    }
    
  • 哈罗单车(HaLuoBicycle)

    public class HaLuoBicycle implements Bicycle {
         
         
    
        private final String color;
        private final String brand;
    
        public HaLuoBicycle() {
         
         
            System.out.println("哈罗单车被实例化");
            this.color = "蓝色";
            this.brand = "哈罗";
        }
    
        @Override
        public String getColor() {
         
         
            return this.color;
        }
    
        @Override
        public String getBrand() {
         
         
            return this.brand;
        }
    }
    
  • 美团单车(MeiTuanBicycle)

    public class MeiTuanBicycle implements Bicycle {
         
         
    
        private final String color;
        private final String brand;
    
        public MeiTuanBicycle() {
         
         
            System.out.println("美团单车被实例化");
            this.color = "黄色";
            this.brand = "美团";
        }
    
        @Override
        public String getColor() {
         
         
            return this.color;
        }
    
        @Override
        public String getBrand() {
         
         
            return this.brand;
        }
    }
    
  • 代码演示

    public static void main(String[] args) {
         
         
        // 实例化一个美团单车工厂
        BicycleFactory meiTuanFactory = new MeiTuanBicycleFactory();
        // 美团单车工厂生产美团单车
        Bicycle meiTuan = meiTuanFactory.create();
        System.out.println(meiTuan.getColor());
        System.out.println(meiTuan.getBrand());
    
        // 实例化一个哈罗单车工厂
        BicycleFactory haLuoFactory = new HaLuoBicycleFactory();
        // 哈罗单车工厂生产哈罗单车
        Bicycle haluo = haLuoFactory.create();
        System.out.println(haluo.getColor());
        System.out.println(haluo.getBrand());
    
    }
    
  • 输出结果

    结果1.jpg

2. 优缺点

从上面的代码演示中,我们可以总结出以下优缺点

优点:

  • 对象的创建过程与使用过程被解耦。如果被创建的对象结构复杂,则可以在工厂方法中完成该对象结构的组装。
  • 工厂方法返回的是产品抽象。因此我们无需关注产品细节,只需要按照产品抽象所定义的方法进行方法调用即可。
  • 当产品的创建过程需要修改时,我们只需在工厂方法中对创建逻辑进行修改即可,无需修改调用方的代码。
  • 适用于结构复杂的对象的创建场景。

缺点:

  • 虽然我们不再关注对象的创建过程,但是代价是需要关注工厂实例的创建过程。其实无论从代码层面还是现实层面来说,工厂对象一般只有一个,我们需要结合单例模式来处理对象工厂的创建和获取逻辑。
  • 一个工厂对象仅能创建一种产品。
  • 每当新增一个产品时,同样也需要创建对应的工厂类。这会导致项目中积累大量的工厂类和产品类。
  • 不适用于简单对象的创建。原本只需一行代码就能完成,而使用工厂模式就需要创建工厂类、工厂方法等,增加代码量。

四、静态工厂

由于工厂模式一般适用于创建复杂对象的场景。当我们需要创建简单对象时,使用工厂模式无疑是一种杀鸡用牛刀的方式。

静态工厂模式是工厂模式的衍生设计模式,用于创建简单的对象。

在静态方法中,只需要一个具体的产品类以及获取对应对象实例的静态方法。

使用上面的案例,我们以美团单车(MeiTuanBicycle)为例。在该类中添加一个静态方法create(),如下所示

public class MeiTuanBicycle implements Bicycle {
   
   

    private final String color;
    private final String brand;

    public MeiTuanBicycle() {
   
   
        System.out.println("美团单车被实例化");
        this.color = "黄色";
        this.brand = "美团";
    }

    @Override
    public String getColor() {
   
   
        return this.color;
    }

    @Override
    public String getBrand() {
   
   
        return this.brand;
    }

    /**
     * 静态工厂
     * @return
     */
    public static Bicycle create() {
   
   
        return new MeiTuanBicycle();
    }
}


public static void main(String[] args) {
   
   

    // 静态方法
    Bicycle bicycle = MeiTuanBicycle.create();
    System.out.println(bicycle.getColor());
    System.out.println(bicycle.getBrand());
}

输出结果如下:

结果2.jpg

1. 应用

静态工厂在jdk中的应用十分广泛,例如Integer.parseInt()方法:

public final class Integer extends Number implements Comparable<Integer> {
   
   
    // ...
    public static int parseInt(String s) throws NumberFormatException {
   
   
        return parseInt(s,10);
    }
    // ...
}

在该静态方法中,Integer类是工厂,它的静态方法parseInt接收字符串作为参数,返回一个Integer对象,因此Integer类又是产品

五、总结

本文介绍了创建型设计模式中的工厂模式和它的衍生设计模式静态工厂模式。并通过具体案例对其讲解,现在对这两中设计模式进行优缺点总结:

  • 工厂模式

    适用于创建复杂对象的场景,并将其创建过程和使用过程解耦

    • 优点
      • 对象的创建过程与使用过程被解耦。如果被创建的对象结构复杂,则可以在工厂方法中完成该对象结构的组装。
      • 工厂方法返回的是产品抽象。因此我们无需关注产品细节,只需要按照产品抽象所定义的方法进行方法调用即可。
      • 当产品的创建过程需要修改时,我们只需在工厂方法中对创建逻辑进行修改即可,无需修改调用方的代码。
      • 适用于结构复杂的对象的创建场景。
    • 缺点
      • 虽然我们不再关注对象的创建过程,但是代价是需要关注工厂实例的创建过程。其实无论从代码层面还是现实层面来说,工厂对象一般只有一个,我们需要结合单例模式来处理对象工厂的创建和获取逻辑。
      • 一个工厂对象仅能创建一种产品。
      • 每当新增一个产品时,同样也需要创建对应的工厂类。这会导致项目中积累大量的工厂类和产品类。
      • 不适用于简单对象的创建。原本只需一行代码就能完成,而使用工厂模式就需要创建工厂类、工厂方法等,增加代码量。
  • 静态工厂模式

    适用于创建复杂对象的场景。

    • 优点
      • 简单




纸上得来终觉浅,绝知此事要躬行。

————————我是万万岁,我们下期再见————————

相关文章
|
6月前
|
设计模式 开发者
探讨常见设计模式 - 工厂方法模式的最佳实践和潜在的实施问题
【4月更文挑战第7天】工厂方法模式是创建型设计模式,提供了一种在不指定具体类情况下创建对象的方式。它定义创建对象的接口,允许子类决定实例化哪个类,从而解耦对象的创建和使用。最佳实践包括明确接口、封装创建逻辑、提供扩展点和避免过度使用。然而,过度工程、违反开闭原则、性能影响和依赖管理是可能的问题。通过权衡利弊并遵循最佳实践,工厂方法模式能在适当场景下提升代码灵活性和可扩展性。
59 1
|
21天前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
2月前
|
设计模式
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
这篇文章详细解释了工厂模式,包括简单工厂、工厂方法和抽象工厂三种类型。每种模式都通过代码示例展示了其应用场景和实现方法,并比较了它们之间的差异。简单工厂模式通过一个工厂类来创建各种产品;工厂方法模式通过定义一个创建对象的接口,由子类决定实例化哪个类;抽象工厂模式提供一个创建相关或依赖对象家族的接口,而不需要明确指定具体类。
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
|
2月前
|
设计模式 Java
Java设计模式-工厂方法模式(4)
Java设计模式-工厂方法模式(4)
|
3月前
|
设计模式 XML 存储
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
文章详细介绍了工厂方法模式(Factory Method Pattern),这是一种创建型设计模式,用于将对象的创建过程委托给多个工厂子类中的某一个,以实现对象创建的封装和扩展性。文章通过日志记录器的实例,展示了工厂方法模式的结构、角色、时序图、代码实现、优点、缺点以及适用环境,并探讨了如何通过配置文件和Java反射机制实现工厂的动态创建。
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
|
3月前
|
设计模式 uml
设计模式-------------工厂模式之工厂方法模式(创建型)
工厂方法模式是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而实现类的实例化推迟到子类中进行,提高了系统的灵活性和可扩展性。
|
5月前
|
设计模式 Java
Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)
Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)
|
5月前
|
设计模式 搜索推荐
工厂方法模式-大话设计模式
工厂方法模式-大话设计模式
|
5月前
|
设计模式 新零售 Java
设计模式最佳套路5 —— 愉快地使用工厂方法模式
工厂模式一般配合策略模式一起使用,当系统中有多种产品(策略),且每种产品有多个实例时,此时适合使用工厂模式:每种产品对应的工厂提供该产品不同实例的创建功能,从而避免调用方和产品创建逻辑的耦合,完美符合迪米特法则(最少知道原则)。
80 6
|
5月前
|
设计模式 XML Java
【设计模式】第三篇:一篇搞定工厂模式【简单工厂、工厂方法模式、抽象工厂模式】
三 结尾 如果文章中有什么不足,欢迎大家留言交流,感谢朋友们的支持! 如果能帮到你的话,那就来关注我吧!如果您更喜欢微信文章的阅读方式,可以关注我的公众号
56 5