工厂方法(Factory Method)设计模式

写在前面:关于设计模式,B站上有很多讲解视频,相关的博客也有不少。本篇博客是在看完B站上的视频讲解后,并查阅了许多相关博客后,进行的总结
学习时看了B站视频:一周带你彻底弄懂23种设计模式 图灵学院

设计模式的运用无非是解决以下几个问题:

  • 扩展性
  • 健壮性
  • 降低耦合
  • 增强内聚

当知道以上本质的时候,在学习或者使用设计模式的时候,经常要思考:

  1. 不用的话,又将带来什么麻烦呢?
  2. 用了这个设计模式,将带来什么样的好处?
  3. 如果不用,后续带来的【麻烦成本】是否可以承受(从个人和团队角度)?

当想清楚以上三个问题的后,我们将可能减少设计模式的滥用,降低陷入「过度设计」的概率。

一、概述

工厂方法(Factory Method)设计模式:定义一个用于创建对象的接口,让子类绝定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类

工厂方法模式的优点:

  • 良好的封装性,代码结构清晰。
  • 扩展性非常优秀,符合开闭原则。在增加产品类的情况系下,只有适当的修改具体的工厂类或扩展一个工厂类,就可以“拥抱变化”。
  • 屏蔽产品类。产品类的实现如何变化,调用者无需关心,它只需关心产品的接口,只要接口保持不变,系统中的上层模块就不需要发生变化。
  • 解耦框架。高层模块只需要知道产品的抽象类,其他实现类都不用关心。

二、完成一个小需求

现在有一个需求,需要我创建一个产品 ProductA,这个需求简单,我很快就写完了:

class ProductA {
    public void function() {
        System.out.println("ProductA do something...");
    }
}

当别人相要使用我创建的 ProductA 时,直接 new ProductA() 即可。这时,就要考虑一个问题,如果以后我的 ProductA 构建方式有变,因为构建ProductA的过程散落在系统的各个角落,则要多个地方。当需要用这个字时,就已经违反了**扩展性原则**(开闭原则)。

因此,我将对象定义方式对象创建方式分离,解耦,即把对象的创建方式放到一个工厂类中Factory

public class Factory {
    public ProductA createProduct() {
        ProductA productA = new ProductA();

        System.out.println("对productA初始化");

        return productA;
    }
}


class ProductA {
    public void function() {
        System.out.println("ProductA do something...");
    }
}

完成了需求后,由于业务发展很快,没过几天,又有了新的需求,需要创建新的产品,产品B和产品C,经过我的分析,发现产品B和产品C在本质上是同一个类型的产品,固我创建了一个产品接口,同时修改了工厂类,以利于工厂方法的统一返回。

public class Factory {
	//增加了产品之后,工厂需要跟据传入的产品标识来返回具体哪一个产品
    public Product createProduct(String flag) {
        Product product;

        if ("ProductA".equals(flag)) {
            product = new ProductA();
            System.out.println("对productA初始化");
        } else if ("ProductB".equals(flag)) {
            product = new ProductB();
            System.out.println("对productB初始化");
        } else {
            product = new ProductC();
            System.out.println("对productC初始化");
        }

		//利用多态, 返回产品接口, 解耦
        return product;
    }
}

//为了能在工厂中统一返回,定义一个产品类,将将产品的公式功能放到接口中
interface Product {
    void function();
}

//产品A
class ProductA implements Product {
    public void function() {
        System.out.println("ProductA do something...");
    }
}
//产品B
class ProductB implements Product {
    public void function() {
        System.out.println("ProductB do something...");
    }
}
//产品C
class ProductC implements Product {
    public void function() {
        System.out.println("ProductC do something...");
    }
}

可能你已经注意到了,每当增加新的产品时,都需要修改工厂类,在工厂类的创建方法中增加一个 if else,又违反了开闭原则。这时,就用到了工厂方法模式来对程序进行优化。

三、使用工厂方法设计模式对程序进行优化

优化方法:将工厂中创建产品的方法变为抽象方法,对每个不同的产品实现相应的方法。

与之前多个if else相比,如果再增加其它产品,不需要修改原来的代码,只需要增加相应的工厂的实现类即可,符合开闭原则。

//使用工厂方法模式对工厂类进行优化,将工厂类中创建对象的方法变为抽象方法。
public interface Factory {
    Product createProduct();
}

class ConcreteProductA implements Factory {

    public Product createProduct() {
        System.out.println("对productA初始化");
        return new ProductA();
    }
}

class ConcreteProductB implements Factory {

    public Product createProduct() {
        System.out.println("对productB初始化");
        return new ProductB();
    }
}

class ConcreteProductC implements Factory {

    public Product createProduct() {
        System.out.println("对productC初始化");
        return new ProductC();
    }
}

//抽象产品接口
interface Product {
    void function();
}

//具体的产品实现类
class ProductA implements Product {
    public void function() {
        System.out.println("ProductA do something...");
    }
}

class ProductB implements Product {
    public void function() {
        System.out.println("ProductB do something...");
    }
}

class ProductC implements Product {
    public void function() {
        System.out.println("ProductC do something...");
    }
}

测试类:

public static void main(String[] args) {
	//直接通过相应的工厂实现类来创建产品对象, 使用接口Factory来去耦合
    Factory factory = new ConcreteProductA();
    Product product = factory.createProduct();
    product.function();
}

四、总结

工厂方法的核心结构有四个角色,分别是抽象工厂、具体工厂、抽象产品、具体产品。一般具体工厂类中的字段为对应具体产品实例化所需的参数。

使用工厂方法模式可以达到解耦、复用和方便后期维护拓展的目的。比如说,具体工厂与具体产品一一对应,可以由不同的团队同时开发。如果不使用工厂方法模式,多个团队要在同一个工厂类中添加多个 if else,麻烦,后期维护也不方便。

发布了52 篇原创文章 · 获赞 93 · 访问量 7174

猜你喜欢

转载自blog.csdn.net/zyx1260168395/article/details/104202101