一文彻底弄懂23设计模式之工厂模式!

简介

工厂模式一般有3种,分别是简单工厂模式,工厂模式,抽象工厂模式,都属于创建型设计模式。讨论的是如何创建对象的问题。就是以各种高逼格的方式最终将一个类的对象new出来,一点也不神秘。

那么我们学习工厂模式的目的是什么?使用场景是什么?

避免紧耦合、重复代码、扩展性差、难以维护等问题,在你需要new一个类的对象的时候,此时各种状况出现啦:

1、直接创建对象的问题,不使用工厂模式,而是在客户端代码中直接创建对象。

问题:

  • 如果 Car 类的名称或包名改变,所有使用 Car 类的地方都需要修改。
  • 客户端代码与 Car 类紧密耦合,难以维护和扩展。
// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 直接创建对象,如果类名改变,所有使用该类的代码都需要修改
        Vehicle vehicle = new Car();
        vehicle.assemble();
    }
}

2、创建过程复杂的问题,在客户端代码中直接处理复杂的创建逻辑。

问题:

  • 创建逻辑分散在客户端代码中,难以管理和维护。
  • 每次需要创建对象时都要重复相同的复杂逻辑。
// 客户端代码
public class Client {
    public static void main(String[] args) {
        Vehicle vehicle = null;
        if (someComplexCondition()) {
            // 复杂的条件判断和对象创建逻辑
            vehicle = new Car();
            vehicle.assemble();
            vehicle.loadAdvancedFeatures();
        } else {
            // 另一条复杂的创建路径
            // ...
        }
    }
    
    private static boolean someComplexCondition() {
        // 复杂的条件判断逻辑
        return true;
    }
}

3、依赖多个其他类的问题在客户端代码中直接处理依赖关系。

问题:

  • 客户端代码需要知道如何创建 Engine 和 Wheel 对象,这增加了客户端的复杂性。
  • 如果 Engine 或 Wheel 的实现发生变化,客户端代码可能需要修改以适应这些变化。
// 客户端代码
public class Client {
    public static void main(String[] args) {
        Engine engine = new Engine();
        Wheel wheel = new Wheel();
        ComplexVehicle vehicle = new ComplexCar(engine, wheel);
        vehicle.assemble();
    }
}

那么工厂模式的作用就体现啦!不直接在客户端创建具体产品的实例,降低了耦合性。

简单工厂模式

定义:简单工厂模式,又叫做静态工厂方法(Static Factory Method)模式,是由一个工厂对象决定创建出哪一种产品类的实例。

UML类图:

简单工厂模式就3个角色:

1、要生产的对象的接口(Computer)
2、要生产的对象(MacComputer,MiComputer)
3、对象工厂(SimpleComputerFactory)

MacComputer 与MiComputer继承了Computer类,SimpleComputerFactory类可以根据不同的条件来生成相应品牌的电脑。

简单工厂模式的核心就是通过一个工厂方法根据不同的条件生产同一类型的产品。例如此例中我们要生产的小米笔记本和苹果笔记本他们是同一类型的产品,会实现同一个接口。

代码实现:

定义电脑的抽象基类以及具体的品牌电脑类

// 定义一个电脑的抽象基类
public abstract class Computer {
    public abstract void setOperationSystem();
}
// 定义具体品牌的电脑类,苹果电脑和小米电脑。
public class MacComputer extends Computer {
    @Override
    public void setOperationSystem() {
        System.out.println("Mac笔记本安装Mac系统");
    }
}
public class MiComputer extends Computer {
    @Override
    public void setOperationSystem() {
        System.out.println("小米笔记本安装Win10系统");
    }
}

定义简单工厂方法类

public class SimpleComputerFactory {
    public static Computer makeComputer(String brand) {
        Computer computer=null;
        switch (brand) {
            case "mac":
                computer=new MacComputer();
                break;
            case "mi":
                computer=new MiComputer();
                break;
            default:
                break;
        }
        return computer;
    }
}

从上面的代码可见,这里其实还用到了里氏替换原则,返回的对象类型是声明类型的子类,也就是面向对象的多态特性。

客户端的使用

public static void main(String[] args) {
    Computer computer= SimpleComputerFactory.makeComputer("mi");
    computer.setOperationSystem();
}

输出打印:小米笔记本安装Win10系统

我们现在可以通过一个静态工厂方法,通过传入不同的参数类型来构建不同的对象实例了,我们将对象的构建过程完全交给了工厂方法类。

总结:

优点:简单易懂,简单工厂模式的实现相对较为简单,易于理解和使用。并且不直接在客户端创建具体产品的实例,降低了耦合性。

缺点:可扩展性有限,一旦某类过多或者某产品变化频繁,就需要不断修改工厂类的代码。违反开闭原则, 每当我们增加一种产品的时候就要去修改工厂方法。为了克服简单工厂方法模式的缺点,工厂模式就被提了出来。

工厂模式

工厂方法模式为每一种产品生成一个对应的工厂,从而替换掉简单工厂方法模式中那个静态工厂方法。

每个工厂只生产一种特定的产品。这样做的好处就是当以后需要增加新的产品时,直接新增加一个对应的工厂就可以了,而不是去修改原有的工厂,符合编程原则的开闭原则。但是缺点也可以想到的啊,工厂方法只能创建一种产品,一种产品只能对应一种工厂,当产品过多就增加了复杂度

UML类图:

代码实现:

// 定义一个电脑的抽象基类
public abstract class Computer {
    public abstract void setOperationSystem();
}
// 实现具体品牌的电脑类
public class MacComputer extends Computer {
    @Override
    public void setOperationSystem() {
        System.out.println("Mac笔记本安装Mac系统");
    }
}
public class MiComputer extends Computer {
    @Override
    public void setOperationSystem() {
        System.out.println("小米笔记本安装Win10系统");
    }
}

定义工厂:

到这里就可以看的出来,简单工厂模式中那个静态工厂方法就被上面的那些具体的工厂类代替了。

// 首先定义一个抽象工厂ComputerFactory接口,里面定义了生产方法
public interface ComputerFactory {
     Computer makeComputer();
}
// 具体的生产工厂
public class MacComputerFactory implements ComputerFactory {
    @Override
    public Computer makeComputer() {
        return new MacComputer();
    }
}
public class MiComputerFactory implements ComputerFactory {
    @Override
    public Computer makeComputer() {
        return new MiComputer();
    }
}

客户端:

使用具体的工厂来生产相应品牌的电脑,例如要生产Mac电脑,就先构建Mac的生产工厂,然后去生产mac电脑。

public static void main(String[] args) {
    //生产Mac电脑
    ComputerFactory macFactory=new MacComputerFactory();
    macFactory.makeComputer().setOperationSystem();

    //生产小米电脑
    ComputerFactory miFactory=new MiComputerFactory();
    miFactory.makeComputer().setOperationSystem();
}

输出:

Mac笔记本安装Mac系统
小米笔记本安装Win10系统

抽象工厂模式

相当于对工厂模式再封装一层。如果你的业务中出现了要依据不同的产品家族来生产其旗下的一系列产品的时候,抽象工厂模式就配上用场了。

这里理解了产品家族概念就容易理解抽象工厂模式了。例如小米公司和苹果公司就是两个不同产品家族,而他们两家都生产笔记本电脑和手机,那么小米的笔记本电脑和苹果的笔记本电脑肯定不一样,手机情况也是如此。这就构成了两个产品家族的系列产品之间比较的关系。

抽象工厂模式在日常开发中使用频率不高,但关键时刻是能起大作用的。

UML类图:

图中有两个产品家族 小米公司 和 苹果公司 ,每个产品家族中包含两种产品,笔记本电脑与手机,所以需要两个工厂。

`AbstractFactory`抽象工厂接口,里面会声明生产品牌家族产品的几个方法,例如这里要生产笔记本电脑和手机,就会有这么两个方法声明。

`XiaoMiFactory`小米产品工厂,实现抽象工厂接口`AbstractFactory`,生产`MiComputer`和`MiPhone`。

`AppleFactory`苹果产品工厂,实现抽象工厂接口`AbstractFactory`,生产`MacComputer`和`IPhone`。

其中`MiComputer`和`MacComputer`是同一类型的产品,都是笔记本电脑,实现同一个接口`Computer`。

`MiPhone`和`IPhone`是同一类型的产品,都是手机,实现同一个接口`MobilePhone`。

到此就一目了然了,富士康需要两个工厂,一个工厂生产小米的笔记本电脑和手机,另一个工厂生产苹果的笔记本电脑和手机。

代码实现:

这里面有一个为电脑安装操作系统的抽象方法,然后定义了两个实现类。

//定义电脑相关的类
//电脑接口
public abstract class Computer {
    public abstract void setOperationSystem();
}
public class MacComputer extends Computer {
    @Override
    public void setOperationSystem() {
        System.out.println("Mac笔记本安装Mac系统");
    }
}
public class MiComputer extends Computer {
    @Override
    public void setOperationSystem() {
        System.out.println("小米笔记本安装Win10系统");
    }
}

里面有一个为手机安装操作系统的抽象方法,然后定义两个实现类

//定义手机相关的类
//手机接口
public abstract class MobilePhone {
    public abstract void setOperationSystem();
}
public class IPhone extends MobilePhone {
    @Override
    public void setOperationSystem() {
        System.out.println("苹果手机安装IOS系统");
    }
}
public class MiPhone extends MobilePhone {
    @Override
    public void setOperationSystem() {
        System.out.println("小米手机安装Android系统");
    }
}

定义工厂类:

这里定义一个抽象工厂的接口,并提供小米和苹果这两个实现类。

//抽象工厂接口
public interface AbstractFactory {
     Computer makeComputer();
     MobilePhoto makeMobilePhone();
}
public class AppleFactory implements AbstractFactory {
    @Override
    public Computer makeComputer() {
        return new MacComputer();
    }

    @Override
    public MobilePhoto makeMobilePhone() {
        return new IPhone();
    }
}
public class XiaoMiFactory implements AbstractFactory {
    @Override
    public Computer makeComputer() {
        return new MiComputer();
    }

    @Override
    public MobilePhoto makeMobilePhone() {
        return new MiPhone();
    }
}

客户端使用:

这里每个工厂生产的是那个品牌家族的一系列产品,而不是一个。例如切换到苹果工厂的话,就会产出苹果笔记本电脑和苹果手机。

public static void main(String[] args) {
    //使用苹果工厂生产苹果公司的系列产品
    AbstractFactory appleFactory=new AppleFactory();
    appleFactory.makeComputer().setOperationSystem();
    appleFactory.makeMobilePhone().setOperationSystem();

   //使用小米工厂生产小米公司的系列产品
    AbstractFactory miFactory=new XiaoMiFactory ();
    miFactory.makeComputer().setOperationSystem();
    miFactory.makeMobilePhone().setOperationSystem();
}

输出:

Mac笔记本安装Mac系统
苹果手机安装IOS系统
小米笔记本安装Win10系统
小米手机安装Android系统

总结

希望这篇文章能帮你更好地理解工厂模式,最后,如果你从本文中有所收获,可否点赞转发支持一下博主,你小小的鼓励,是激发博主持续写作的动力...

  • 34
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
责任链设计模式是一种行为型设计模式,用于将请求的发送者和接收者解耦,使多个对象都有机会处理该请求。该模式将这些对象串成链,并沿着这条链传递请求,直到有一个对象能够处理它为止。 责任链模式的核心是定义一个处理请求的抽象类或接口,然后让多个具体的处理者对象继承或实现这个类/接口。每个具体的处理者对象都包含一个对下一个处理者对象的引用,形成一个链式结构。 当一个请求进入责任链时,责任链中的每个处理者都有机会处理该请求。如果可以处理请求,则进行处理;如果不能处理,则将请求传递给下一个处理者,直到有一个处理者能够处理它。 责任链模式的关键点是要找到合适的处理者顺序和条件。通常情况下,责任链模式适用于以下情况: 1. 有多个对象可以处理同一类型的请求,但具体由哪个对象来处理由运行时决定。 2. 不明确请求的接收者,希望请求在一个对象链中流动,直到被处理。 3. 需要动态地指定可以处理请求的对象集合。 使用责任链模式可以实现请求发送者和接收者的解耦,增加代码的灵活性和可扩展性。但同时也需要注意责任链的长度和效率问题,避免责任链过长或造成性能问题。 总结一下,责任链设计模式是一种将请求发送者和接收者解耦的设计模式,通过将多个处理者对象串成链,沿着这条链传递请求,直到有一个处理者能够处理它。这样可以增加代码的灵活性和可扩展性,适用于有多个对象可以处理同一类型请求的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值