裴大头-秦可爱

裴大头-秦可爱

Java 23种设计模式——工厂方法模式(Factory Method)以及抽象工厂模式(Abstract Factory)

发表于 2023-10-17
裴大头
阅读量 392
更新于 2023-10-29

工厂方法模式(Factory Method)

一、问题

在软件设计中,我们经常遇到需要创建不同类型对象的情况。但是,如果直接在代码中实例化对象,会使代码紧密耦合在一起,难以维护和扩展。此外,如果对象的创建方式需要变化,那么就需要在整个代码中进行大量的修改。工厂方法模式旨在解决这个问题。

二、解决方案

工厂方法模式提供了一个创建对象的接口,但是将具体的对象创建延迟到子类中。这样,客户端代码不需要知道要创建的具体对象的类,只需要通过工厂方法来创建对象。这使得客户端代码与具体对象的创建解耦,提高了代码的灵活性和可维护性。 在工厂方法模式中,通常会定义一个抽象工厂类,其中包含一个创建对象的抽象方法,而具体的对象创建则由具体的子类实现。这样,每个具体的子类都可以根据需要创建不同类型的对象,而客户端代码只需要通过抽象工厂类来调用工厂方法,而不需要关心具体的对象创建细节。

三、效果

工厂方法模式的优点包括:

  • 松耦合:客户端代码与具体对象的创建解耦,使得系统更具弹性和可维护性。
  • 扩展性:通过添加新的具体工厂和产品子类,可以很容易地扩展系统以支持新的对象类型。
  • 封装性:将对象的创建集中在工厂类中,封装了对象的创建细节,使得客户端代码更简洁。

然而,工厂方法模式也可能引入一些额外的复杂性,因为需要定义多个工厂类和产品类的层次结构。这可能会导致系统中类的数量增加。在选择使用工厂方法模式时,需要根据具体情况进行权衡。 工厂方法模式在实际应用中非常常见,例如,图形库可以使用工厂方法模式来创建不同类型的图形对象,数据库访问框架可以使用工厂方法模式来创建不同类型的数据库连接等。

四、代码

1697535059530.png

1.Animal.java

/**
 * Animal
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 13:57
 * @description 动物抽象类
 */
public interface Animal {
    // 叫
    public void sound();
}
java

2.Cat.java

/**
 * Cat
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 13:57
 * @description 猫咪类
 */
public class Cat implements Animal {
    @Override
    public void sound() {
        System.out.println("喵喵喵");
    }
}
java

3.Dog.java

/**
 * Dog
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 13:58
 * @description 小狗类
 */
public class Dog implements Animal {
    @Override
    public void sound() {
        System.out.println("汪汪汪");
    }
}
java

4.AnimalFactory.java

/**
 * AnimalFactory
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 13:58
 * @description 动物工厂抽象类
 */
public abstract class AnimalFactory {
    // 创建动物类对象
    public abstract Animal createAnimal();
}
java

5.CatFactory.java

/**
 * CatFactory
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 16:22
 * @description 猫咪工厂
 */
public class CatFactory extends AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Cat();
    }
}
java

6.DogFactory.java

/**
 * DogFactory
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 16:23
 * @description 小狗工厂
 */
public class DogFactory extends AnimalFactory{
    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}
java

7.Main.java

/**
 * Main
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:52
 * @description 工厂方法模式客户端
 */
public class Main {
    public static void main(String[] args) {
        // 初始化猫咪工厂
        AnimalFactory catFactory = new CatFactory();
        Animal cat = catFactory.createAnimal();
        cat.sound();
        // 初始化小狗工厂
        AnimalFactory dogFactory = new DogFactory();
        Animal dog = dogFactory.createAnimal();
        dog.sound();
    }
}
java

8.打印结果

image.png

抽象工厂模式(Abstract Factory)

一、问题

在某些情况下,需要创建一系列相关或相互依赖的对象,这些对象属于一组相关的产品族。同时,系统需要保证这些产品族之间的一致性。如果直接在代码中创建这些对象,会使得代码与具体产品的细节紧密耦合,不利于后续的扩展和维护。

二、解决方案

抽象工厂模式提供了一个接口,用于创建一系列相关或相互依赖的对象。通过使用抽象工厂接口及其具体实现,可以将对象的创建与客户端代码分离,从而实现系统的松耦合。抽象工厂模式涉及多个角色:

  • 抽象工厂(Abstract Factory):声明了一组用于创建不同产品的抽象方法。具体的工厂类必须实现这些方法来创建具体的产品对象。
  • 具体工厂(Concrete Factory):实现抽象工厂接口,负责创建特定种类的产品对象。
  • 抽象产品(Abstract Product):定义了产品的通用接口,具体产品必须实现这个接口。
  • 具体产品(Concrete Product):实现抽象产品接口,是抽象工厂创建的实际对象。

三、效果

抽象工厂模式的使用可以带来以下效果:

  • 产品族一致性:抽象工厂确保创建的产品是一组相关的产品族,保证了这些产品之间的一致性。
  • 松耦合:客户端代码不需要直接依赖于具体产品,只需要通过抽象工厂接口创建产品,从而降低了代码的耦合度。
  • 可扩展性:增加新的产品族或产品变得相对容易,只需要添加新的具体工厂和产品类即可,不需要修改现有代码。
  • 限制:抽象工厂模式要求系统中的每个产品族都必须有一个对应的具体工厂,这可能增加了系统的复杂性。

抽象工厂模式适用于需要创建一系列相关产品并保证它们之间一致性的情况,例如图形界面库中的UI元素,不同操作系统下的界面组件等。通过使用抽象工厂模式,可以更好地管理和组织这些产品的创建过程。

四、代码

image.png

1.OperatingSystem.java

/**
 * OperatingSystem
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:39
 * @description 抽象产品接口:操作系统
 */
public interface OperatingSystem {
    /**
     * 启动
     */
    void run();
}
java

2.WindowsOS.java

/**
 * WindowsOS
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:39
 * @description 具体产品:Window操作系统
 */
public class WindowsOS implements OperatingSystem {

    @Override
    public void run() {
        System.out.println("Windows系统启动~");
    }
}
java

3.Linux.java

/**
 * LinuxOS
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:40
 * @description 具体产品:Linux操作系统
 */
public class LinuxOS implements OperatingSystem {
    @Override
    public void run() {
        System.out.println("Linux系统启动~");
    }
}
java

4.Application.java

/**
 * Application
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:41
 * @description 抽象产品接口:应用程序
 */
public interface Application {
    /**
     * 打开
     */
    void open();
}
java

5.WeChat.java

/**
 * WeChat
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:44
 * @description 具体产品:微信
 */
public class WeChat implements Application {
    @Override
    public void open() {
        System.out.println("打开微信~");
    }
}
java

6.Vim.java

/**
 * Vim
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:45
 * @description 具体产品:Vim
 */
public class Vim implements Application {
    @Override
    public void open() {
        System.out.println("打开Vim~");
    }
}
java

7.SoftwareFactory.java

/**
 * SoftwareFactory
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:47
 * @description 抽象工厂接口
 */
public interface SoftwareFactory {
    /**
     * 创建操作系统
     * @return 操作系统
     */
    OperatingSystem createOperatingSystem();

    /**
     * 打开程序
     * @return 程序
     */
    Application openApplication();
}
java

8.WindowsFactory.java

/**
 * WindowsFactory
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:49
 * @description 具体工厂:Windows工厂
 */
public class WindowsFactory implements SoftwareFactory {
    @Override
    public OperatingSystem createOperatingSystem() {
        return new WindowsOS();
    }

    @Override
    public Application openApplication() {
        return new WeChat();
    }
}
java

9.LinuxFactory.java

/**
 * LinuxFactory
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:50
 * @description 具体工厂:Linux工厂
 */
public class LinuxFactory implements SoftwareFactory {
    @Override
    public OperatingSystem createOperatingSystem() {
        return new LinuxOS();
    }
    @Override
    public Application openApplication() {
        return new Vim();
    }
}
java

10.Main.java

/**
 * Main
 *
 * @author 裴浩宇
 * @version 1.0
 * @date 2023/10/17 17:52
 * @description 抽象工厂模式客户端
 */
public class Main {
    public static void main(String[] args) {
        // 初始化Windows工厂
        SoftwareFactory windowsFactory = new WindowsFactory();
        // 初始化操作系统
        OperatingSystem windowsOS = windowsFactory.createOperatingSystem();
        // 启动
        windowsOS.run();
        // 初始化应用程序
        Application wechat = windowsFactory.openApplication();
        // 打开
        wechat.open();
        // 初始化Linux操作系统
        SoftwareFactory linuxFactory = new LinuxFactory();
        // 初始化操作系统
        OperatingSystem linuxOS = linuxFactory.createOperatingSystem();
        // 启动
        linuxOS.run();
        // 初始化应用程序
        Application vim = linuxFactory.openApplication();
        // 打开
        vim.open();
    }
}
java

11.打印结果

image.png

源码

源码下载

Java 23种设计模式(含源码)

评论
来发一针见血的评论吧!
表情
  • 裴大头

    男博主

    IP:济南市

    2023-10-17 17:24

    工厂方法模式(Factory Method Pattern)和抽象工厂模式(Abstract Factory Pattern)都属于创建型设计模式,但它们有以下几个区别:

    1. 目的不同:
    - 工厂方法模式旨在定义一个用于创建对象的接口,但具体的对象创建交给子类实现。它将创建对象的过程延迟到子类中,使得拥有不同的实现方式。
    - 抽象工厂模式旨在提供一个创建相关或依赖对象族的接口,而无需指定具体的类。它通过将具体的对象创建与客户端分离,实现了实例化具体类的关系解耦。

    2. 参与角色不同:
    - 工厂方法模式中,一般包含一个抽象工厂类,它声明了一个创建对象的工厂方法,由子类去实现这个方法来具体创建对象。
    - 抽象工厂模式中,一般包含多个抽象产品类、多个具体产品类和一个抽象工厂类。抽象工厂类声明了多个用于创建不同产品族的方法,每个方法返回对应产品族的抽象产品对象。

    3. 创建对象的方式不同:
    - 工厂方法模式中,每个具体工厂类负责创建一种具体产品对象。客户端通过调用具体工厂类的工厂方法来获取具体产品对象。
    - 抽象工厂模式中,每个具体工厂类负责创建一整个产品族的对象。客户端通过调用具体工厂类的方法来获取产品族的所有对象。

    4. 扩展性不同:
    - 工厂方法模式具有良好的扩展性,可以很方便地增加新的具体工厂类来创建新的具体产品对象。
    - 抽象工厂模式较为复杂,当需要增加新的产品族时,需要修改抽象工厂接口以及所有的具体工厂类,扩展性相对较差。

    综上所述,工厂方法模式更加关注单一对象的创建过程,而抽象工厂模式则更注重创建一整个产品族的对象。两者适用于不同的场景和需求。

    0
    回复
      共0条回复,点击查看
  • 裴大头

    男博主

    IP:济南市

    2023-10-17 15:46

    简单工厂模式的优点在于客户端无需了解具体产品类的创建细节,只需通过工厂类来创建对象,并且工厂类可以根据客户端的需求来动态创建不同类型的对象。但是缺点也比较明显,如果需要创建的产品类数量较多,则工厂类的代码会变得很臃肿,不便于维护。

    0
    回复
      共0条回复,点击查看
推荐文章
  • Vue项目代码规范

    1点赞1评论

  • JavaScript 的事件循环机制

    1点赞1评论

  • 聊一聊我的文本编辑器

    1点赞11评论

  • JavaScript的常用遍历方法整理

    1点赞8评论

  • 前端面试精选-基础篇

    1点赞0评论

Crafted with by Pei你看雪

小破站居然运行了 865 天访客 23357

© 2023 Pei你看雪鲁ICP备19037910号-2