设计模式之工厂模式-----------超级详细,细节怪!

1.工厂模式的作用

工厂模式的作用主要有以下几点:

  1. 封装对象创建:隐藏对象创建的复杂性,客户端只需调用工厂方法,而不必了解具体实现。

  2. 降低耦合度:客户端与具体产品类解耦,依赖接口或抽象类,便于维护和扩展。

  3. 确保产品一致性:在抽象工厂模式中,保证同一工厂创建的产品属于同一产品族,保持一致性。

  4. 增强扩展性:便于添加新产品类型,遵循开闭原则,不需修改现有代码。

  5. 集中管理创建过程:统一管理和控制对象创建,便于加入日志、监控等功能。

工厂模式使代码更加灵活、易于维护,并且支持系统的扩展和模块化设计。简单来说就是用来封装对象,便于维护和扩展,这里面涉及到一些设计原则,工厂模式主要涉及到单一职责原则、开闭原则、依赖倒转原则,这些原则我在此文章中会简单介绍,如果想要深入了解,可以关注点赞加收藏,后续我会在设计模式专栏中持续更新!

2.工厂模式的分类

工厂模式主要分为三类:

1. 简单工厂模式

  • 定义:通过一个静态方法,根据传入的参数决定创建哪一种产品对象。
  • 特点:不属于“设计模式”的正式分类,但常用。简化对象创建过程,适合简单场景。
  • 缺点:不易扩展,增加新产品需要修改工厂类代码,违反开闭原则(对扩展开放,对修改关闭)。

2. 工厂方法模式

  • 定义:定义一个用于创建对象的接口,由子类决定实例化哪一个具体产品类。
  • 特点:将对象的创建推迟到子类进行,符合开闭原则,便于扩展。
  • 优点:添加新产品时无需修改现有代码,只需增加新的具体工厂类。
  • 缺点:增加了类的数量,复杂性较高。

3. 抽象工厂模式

  • 定义:提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们的具体类。
  • 特点:适用于创建产品族的情况,比如同一系列的不同产品(按钮、文本框等)。
  • 优点:确保相关产品的一致性,易于扩展新的产品族。
  • 缺点:添加新产品族时,所有工厂类都需要修改,增加了系统复杂性。

3.简单工厂模式

简单工厂的定义是:工厂根据客户端传的参数而返回不同的实例,返回的实例具有共同的父类或接口,此举满足了开闭原则。

由于只有一个工厂类,所以在工厂中创建的对象尽可能的少,不然容易造成逻辑复杂,代码臃肿,难以维护,其次,因为工厂封装了对象的创建过程,所以客户端不需要考虑对象创建的过程。

接下来,我全部以汽车为实例进行讲解:

首先,先定一个产品的共同行为接口。

//定一个产品拥有共同行为的接口
interface Car {
    //汽车都能跑,这是一个汽车的共同行为
    void run();
}

有很多人会疑问,我来学工厂模式,为什么还要定义产品的接口,多费事,多麻烦!因为在实现简单工厂模式的同时,我们还要保持设计原则之一的开闭原则,这样代码才具有健壮性。

其次,再去实现具体的产品:

//XiaoMiCar产品
public class XiaoMiCar implements Car {
    //这里重写方法
    @Override
    public void run() {
        System.out.printIn("小米汽车正在行驶中.....");
    }
    
}
//比亚迪汽车产品
public class BydCar implements Car {
    //重写方法
    @Override
    public void run() {
        System.out.printIn("比亚迪汽车正在行驶.....");
    }
}

 然后,我们有个具体的产品,就要要工厂代替客户端去生产产品对吧,所以我们再定义一个工厂类,根据客户端传的参数返回不同的产品。

class SimpleFactory {
    public static Car createCar(String type) {
        if(type.equals("小米汽车")){
            return new XiaoMiCar();
        } else if(type.equals("比亚迪汽车")){
            return new BydCar();
        } else {
            throw new IllegalArgumentException("没有你想要的汽车");
        }
    }
}

 最后,客户端代码如下:

public class SimpleFactoryPatternDemo {

    public static void main(String arg[]) {

        Car xiaoMiCar = SimpleFactory.createCar("小米汽车");
        xiaoMiCar.run();

        Car bydCar = SimpleFactory.createCar("比亚迪汽车");
        bydCar.run();
        
    }
}

这样,就可以根据客户端不同的需求来创建不同的对象。

优点:只需要一个工厂创建对象,代码量少。

缺点:系统扩展困难,新增产品要修改工厂逻辑,当产品较多的时候,对造成工厂逻辑复杂,不易于 扩展。

4.工厂方法模式

工厂方法模式是简单工厂的仅一步深化,在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。每个对象都有一个与之对应的工厂。

有了前面的基础,我直接上代码!

首先,还是和前面一样,先定义一个产品接口:

//定一个产品拥有共同行为的接口
interface Car {
    //汽车都能跑,这是一个汽车的共同行为
    void run();
}

其次,定义具体的产品:

//XiaoMiCar产品
public class XiaoMiCar implements Car {
    //这里重写方法
    @Override
    public void run() {
        System.out.printIn("小米汽车正在行驶中.....");
    }
    
}
//比亚迪汽车产品
public class BydCar implements Car {
    //重写方法
    @Override
    public void run() {
        System.out.printIn("比亚迪汽车正在行驶.....");
    }
}

然后,这一步就有所不同,前面的简单工厂是在这一步直接创建了一个工厂的大工厂,而这里,我前面讲过,每个具体的产品要有自己的工厂,但是这里我们先不急创建工厂,我们要先创建一个所有工厂的共同父类接口,这里的原理和所有具体产品都有一个共同的产品接口是一样,也要满足开闭原则。不写也行的,但这样就是典型的对代码不负责任,最终成为屎山代码!!!

interface CarFactory {
    Car getCar();
}

紧接着,我们来实现一对一的工厂类:

先是小米汽车工厂

class XiaoMiCarFactory implements CarFactory {
    @Override
    public Car getCar(){
        return new XiaoMiCar();
    }
}

然后是比亚迪汽车工厂

class BydCarFactory implements CarFactory {
    @Override
    public Car getCar(){
        return new BydCar();
    }
}

最后客户端指定工厂来返回具体实例:

CarFactory factory = new XiaoMiCarFactory();
Car xiaoMiCar = factory.getCar();
xiaoMiCar.run();

和简单工厂相比,最根本的区别在于简单工厂是一个大工厂,工厂方法模式是一个个具体的工厂,专人专事。其中,这些工厂也实现了一个基类也就是CarFactory

优点:新增产品类不需要修改现有的代码,直接增加新产品和新工厂就好,然后继承工厂基类。

5.抽象工厂模式

抽象工厂模式它提供一个接口,用于创建一系列相关或互相依赖的对象,而无需指定它们的具体类。通过这个模式,可以确保同一系列的对象在一起使用时是兼容的,并且在需要扩展新的产品系列时,不需要修改现有代码。可以这么理解,就是工厂方法模式的复数形式,哈哈哈哈哈,我是这样理解的。看一下他的作用就明白了

作用:

  • 产品族的管理:抽象工厂模式用于创建一系列相关联的产品(如按钮、文本框、复选框等),并保证这些产品在一起使用时的一致性。
  • 提高系统的可扩展性:通过扩展新的具体工厂类,可以轻松添加新的产品族,而无需修改现有代码。

假设你有两个产品族:WindowsMacOS,它们各自包含 ButtonCheckbox 两种产品。

// 抽象产品接口
interface Button {
    void click();
}

interface Checkbox {
    void check();
}

// 具体产品类
class WindowsButton implements Button {
    @Override
    public void click() {
        System.out.println("Windows Button clicked");
    }
}

class MacOSButton implements Button {
    @Override
    public void click() {
        System.out.println("MacOS Button clicked");
    }
}

class WindowsCheckbox implements Checkbox {
    @Override
    public void check() {
        System.out.println("Windows Checkbox checked");
    }
}

class MacOSCheckbox implements Checkbox {
    @Override
    public void check() {
        System.out.println("MacOS Checkbox checked");
    }
}

// 抽象工厂接口
interface UIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

// 具体工厂类
class WindowsFactory implements UIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public Checkbox createCheckbox() {
        return new WindowsCheckbox();
    }
}

class MacOSFactory implements UIFactory {
    @Override
    public Button createButton() {
        return new MacOSButton();
    }

    @Override
    public Checkbox createCheckbox() {
        return new MacOSCheckbox();
    }
}

// 客户端代码
public class AbstractFactoryPatternDemo {
    public static void main(String[] args) {
        UIFactory factory = new WindowsFactory();  // 可替换为 MacOSFactory
        Button button = factory.createButton();
        Checkbox checkbox = factory.createCheckbox();

        button.click();  // 输出: Windows Button clicked
        checkbox.check();  // 输出: Windows Checkbox checked
    }
}

适用场景:

  • 和工厂方法一样客户端不需要知道它所创建的对象的类。
  • 需要一组对象共同完成某种功能时。并且可能存在多组对象完成不同功能的情况。
  • 系统结构稳定,不会频繁的增加对象。(因为一旦增加就需要修改原有代码,不符合开闭原则)

至此,工厂模式就完结了,文章中涉及到许多设计原则,这些原则,我会明天更新在设计模式的专栏当中,其他的设计模式我也会后续一天一更,尽可能的快的总结!感谢大家支持! 

 

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值