设计模式详解(三):工厂方法

目录导航

  • 抽象工厂及其作用
  • 工厂方法的好处
  • 工厂方法的实现
    • 关系图
    • 实现步骤
  • 工厂方法的适用场景
  • 工厂方法举例

抽象工厂及其作用

工厂方法是一种创建型设计模式。所谓创建型设计模式是说针对创建对象方面的设计模式。在面向对象的编程语言里,我们通过对象间的相互协作,共同完成复杂的业务逻辑,因为对象之间存在着依赖关系。

当对象A依赖对象B时,我们不采取直接创建对象B的方式,即B productB = new B()

java 复制代码
public class A {
    public void bizLogic(){
        //do something
        ...
        B b = new B();
        //do something
        ...
    }
}

而是在A的父类中定义一个返回B类型对象的方法,通常该方法的返回值是接口类型或者BaseClass类型,允许A的子类覆盖该方法,返回不同的对象类型C,但需满足C extends/implements B。在父类A中,该方法既可以是抽象方法,也可以不定义为抽象方法(返回默认的B类型实例)。

java 复制代码
public abstract class A {
    public void bizLogic(){
        //do something
        ...
        B b = createB();
        //do something
        ...
    }
    
    
    public abstract B createB();
}

这种创建对象的设计模式称之为工厂方法。为什么叫工厂方法?通常对象被称之产品,而生产产品的工具称之为工厂,由于在这种设计模式中,是一个方法承担工厂的作用,所以称之为工厂方法。

工厂方法的好处

乍一看,似乎我们只是把创建对象B的代码抽取到了一个方法中而已,实际上这种设计模式有着诸多好处。

  • 解耦。避免对象A与被依赖方B的具体实现类强耦合,对于A来说,我只需要一个B类型的实例,并不关心具体实现类,利于程序扩展。
  • 符合单一职责的原则。类的设计原则之一便是单一职责。A的主要职责肯定不是创建B对象,而是依赖B对象完成特定的业务功能。将创建B的代码单独抽离,使得A的职责更加清晰。
  • 符合开闭原则。后续可以引入多个B的子类而不会"惊动"A的代码。

工厂方法的实现

关系图

依赖方A我们称之为Creator,即需要创建产品B的类,被依赖方B称之为Product,即产品。它们的关系图如下:

实现步骤

  1. 为对象B定义一个统一的接口B_interface或基类B_base_class,并在其中定义对外提供功能的统一接口方法,定义一批B的子类,以实现差异化功能,所有的子类需实现B_interface或继承B_base_class
  2. 在对象A的父类中定义一个返回B对象的方法,返回值类型为B_interfaceB_base_class。该方法可为抽象方法,也可返回默认的B实例,视实际使用需求而定。
  3. 将对象A中直接创建对象B的代码全部替换成定义好的工厂方法。
  4. 定义一批A的子类,在子类中重写工厂方法,返回不同的B实例。

工厂方法的适用场景

  1. 当我们实现业务代码时,无法提前获知所依赖对象的具体类型,这通常发生在顶层设计的时候,此时可以通过工厂方法抽象定义所需的对象。
  2. 我们打包一个库给他人使用时,其中一些业务逻辑,我们无法确定用户是应该使用库里定义好的一些默认组件,还是想使用自己扩展后的组件(继承默认组件),可通过工厂方法解决该问题。
  3. 被依赖的对象可能比较特殊,占用一定的系统资源,所以不能任意创建,可在工厂方法内实现一定的控制逻辑,控制对象的创建过程,避免资源浪费。

工厂方法举例

工厂方法在代码设计中几乎无处不在,这里举一个Android中的例子。我们在创建Fragment时都要继承Fragment基类,并实现onCreateView方法,该方法负责创建一个视图对象,由于基类并不清楚子类会返回一个什么样的视图对象,所以该方法是一个工厂方法,返回值定义为基类View

java 复制代码
public class SubFragment extends Fragment {

   @Nullable
   @Override
   public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
       return new SubView(getContext());
   }
}
相关推荐
我命由我123451 分钟前
Android 对话框 - 对话框全屏显示(设置 Window 属性、使用自定义样式、继承 DialogFragment 实现、继承 Dialog 实现)
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
Full Stack Developme11 分钟前
java.net 包详解
java·python·.net
非凡的世界28 分钟前
深入理解 PHP 框架里的设计模式
开发语言·设计模式·php
一叶飘零_sweeeet30 分钟前
深入 Spring 内核:解密 15 种设计模式的实战应用与底层实现
java·spring·设计模式
凤山老林34 分钟前
排序算法:详解插入排序
java·开发语言·后端·算法·排序算法
彦楠38 分钟前
IDEA实用快捷键
java·ide·intellij-idea
豆沙沙包?1 小时前
2025年--Lc197-077. 排序链表(链表,尾插法)--Java版
java·数据结构·链表
m0_651593911 小时前
深入理解软件设计中的协议与规范:从理论到Java实践
java·软件工程·代码规范·设计规范
Mr_WangAndy1 小时前
C++设计模式_行为型模式_状态模式State
c++·设计模式·状态模式
Knight_AL1 小时前
Tomcat 类加载器隔离机制的实际应用
java·tomcat