设计模式--工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,它提供了一种创建对象的方式,使得创建对象的过程与使用对象的过程分离。

工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。

通过使用工厂模式,可以将对象的创建逻辑封装在一个工厂类中,而不是在客户端代码中直接实例化对象,这样可以提高代码的可维护性和可扩展性。

工厂模式的类型

1、简单工厂模式(Simple Factory Pattern)

  • 简单工厂模式不是一个正式的设计模式,但它是工厂模式的基础。它使用一个单独的工厂类来创建不同的对象,根据传入的参数决定创建哪种类型的对象。

2、工厂方法模式(Factory Method Pattern)

  • 工厂方法模式定义了一个创建对象的接口,但由子类决定实例化哪个类。工厂方法将对象的创建延迟到子类。

3、抽象工厂模式(Abstract Factory Pattern)

  • 抽象工厂模式提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。

实际应用示例

假如说我们创建一个工厂,用来创造人,可以三种肤色的人,分别是黄人、白人、黑人

下面让我们用简单工厂模式来实现

简单工厂模式

类图如下图所示

结构组成
Product(产品角色):定义产品的公共接口或抽象类
ConcreteProduct(具体产品角色):实现Product接口的具体产品类
Factory(工厂角色):负责创建具体产品实例的类

首先创建接口,用来约定定义人的肤色和行为

java 复制代码
public interface Human {

    void printColor();

    void talk();

}

下面我们实现接口

实现黄种人

java 复制代码
public class YellowHuman implements Human{
    @Override
    public void printColor() {
        System.out.println("黄人");
    }

    @Override
    public void talk() {
        System.out.println("黄人说话");
    }
}

实现白种人

java 复制代码
public class WhiteHuman implements Human{
    @Override
    public void printColor() {
        System.out.println("白人");
    }

    @Override
    public void talk() {
        System.out.println("白人说话!");

    }
}

实现黑种人

java 复制代码
public class BlackHuman implements Human{
    @Override
    public void printColor() {
        System.out.println("黑人");
    }

    @Override
    public void talk() {
        System.out.println("黑人说话");

    }
}

目前三个人种的实体都已实现,都实体类种都实现了接口种人员说话和人种类别

下面让我们来创建工厂类

java 复制代码
public class HumanFactory {

    public static Human createHuman(String humanType){
        if("black".equalsIgnoreCase(humanType)){
            return new BlackHuman();
        }else if("white".equalsIgnoreCase(humanType)){
            return new WhiteHuman();
        }else if ("yellow".equalsIgnoreCase(humanType)){
            return new YellowHuman();
        }else{
            return null;
        }
    }
}

现在工厂类也创建好了,下面我们测试工厂类调用

java 复制代码
    @Test
    public void test1(){
        Human blackFactory = HumanFactory.createHuman("black");
        blackFactory.printColor();
        blackFactory.talk();

        Human whiteFactory = HumanFactory.createHuman("white");
        whiteFactory.printColor();
        whiteFactory.talk();

        Human yellowFactory = HumanFactory.createHuman("yellow");
        yellowFactory.printColor();
        yellowFactory.talk();
    }

执行结果如下

java 复制代码
黑人
黑人说话
白人
白人说话!
黄人
黄人说话

Process finished with exit code 0

下面让我们总结一下简单工厂模式的优缺点

优点:

1、封装性好:隐藏了对象创建的细节

2、扩展性强:新增产品只需要修改工厂类

3、解耦:客户端与具体产品类解耦

缺点:

1、违反开闭原则:添加新产品需要修改工厂类(添加新的需要在工厂类中添加if分支)

2、工厂职责过重:承担过多创建逻辑

3、可扩展性差:当产品类型过多的时候,工厂类会变得很复杂

适用场景

--创建对象的逻辑较为复杂

--客户端不需要知道具体的产品实现

--需要同意管理对象的创建过程

--产品类型相对固定且数量不多

与其他模式的关系

--工厂方法模式:是简单工厂模式的进一步抽象和改进

--抽象工厂模式:可以看作多个简单工厂的组合

--策略模式:在某些情况下可以互相替换使用

工厂方法模式

类图如下:

结构组成
Product(产品角色):定义产品的公共接口或抽象类
ConcreteProduct(具体产品角色):实现Product接口的具体产品类
Factory(抽象工厂角色):声明工厂方法,返回一个Product类型的对象
ConcreteFactory(具体工厂角色):实现抽象工厂方法,返回具体的Product实例

首先创建人的接口,用来约定人的肤色和行为

java 复制代码
public interface Human {

    void printColor();

    void talk();

}

其次我们还来实现人种接口

java 复制代码
public class BlackHuman implements Human {
    @Override
    public void printColor() {
        System.out.println("黑人");
    }

    @Override
    public void talk() {
        System.out.println("黑人说话");

    }
}



public class WhiteHuman implements Human {
    @Override
    public void printColor() {
        System.out.println("白人");
    }

    @Override
    public void talk() {
        System.out.println("白人说话!");

    }
}


public class YellowHuman implements Human {
    @Override
    public void printColor() {
        System.out.println("黄人");
    }

    @Override
    public void talk() {
        System.out.println("黄人说话");
    }
}

定义工厂的抽象方类

java 复制代码
public abstract class AbstractHumanFactory {

    public abstract Human createHuman();
}

实现工厂抽象类

java 复制代码
public class BlackHumanFactory extends AbstractHumanFactory{
    @Override
    public Human createHuman() {
        return new BlackHuman();
    }
}

public class WhiteHumanFactory extends AbstractHumanFactory{

    @Override
    public Human createHuman() {
        return new WhiteHuman();
    }
}

public class YellowHumanFactory extends AbstractHumanFactory{
    @Override
    public Human createHuman() {
        return new YellowHuman();
    }
}

测试调用

java 复制代码
开始黑人ShowTime
黑人
黑人说话
开始白人ShowTime
白人
白人说话!
开始黄人ShowTime
黄人
黄人说话

Process finished with exit code 0

下面我们总结一下工厂方法模式的优缺点

优点:

1、符合开闭原则:增加新产品只需要扩展具体工厂,无需修改现有代码

2、单一职责原则:每个工厂孩子负责创建特定类型的产品

3、可扩展性好:支持添加新的产品族

4、灵活性强:子类可以延迟对象的创建到合适的工厂

缺点:

1、类数量增多:每增加一个产品就需要增加一个对应的具体工厂类

2、复杂度增加:对于简单的产品创建,可能会显得过于复杂

3、层次较多:继承结构校审,可能导致系统复杂

适用场景

--产品等级结构稳定:产品种类基本不变,但具体实现经常变化

--需要隔离产品的创建和使用:客户端不关心产品如何创建的

--需要扩展产品系列:系统需要支持多种产品系列

--框架设计:为框架用户提供扩展点

与其他设计模式的关系

--简单工厂模式:工厂方法是对简单工厂的改进,解决了违反开闭原则的问题

--抽象工厂模式:工厂方法模式的扩展,用于创建产品族

--模板方法模式:工厂方法是模板方法的一种特殊应用

--策略模式:可以配合使用,工厂创建不同的策略对象

抽象工厂模式

在工厂方法模式中,一个具体的工厂负责生产一类具体的产品,即一对一的关系,但是如果需要一个具体的工厂生产多种产品对象,比如,生产不同肤色的男人和女人,那么就需要用到抽象工厂模式

类图如下

结构组成
AbstractFactory(抽象工厂):声明了一组创建抽象产品的抽象方法
ConcreteFactory(具体工厂):实现了创建具体产品的方法
AbstractProduct(抽象产品):定义了产品的规范
ConcreteProduct(具体产品):实现抽象产品接口的具体产品
Client(客户端):仅使用由抽象类型构成的系列产品

抽象工厂我们定义了两个方法,createMan()和createWoman()用来表示生产男人和女人,不管男人还是女人,都有不同的肤色,所以我们定义了三个子工厂用来创建不同肤色的人(包括男人和女人),这三个子工厂重写父类工厂的两个方法,具体实现如下

首先定义接口和两个实现类

java 复制代码
public interface Human {
    //打印肤色
    public void printColor();
}
java 复制代码
public abstract class Man implements Human{
    public void pringGender(){
        System.out.println("我是男性");
    }
    @Override
    public abstract void printColor();
}
java 复制代码
public abstract class Woman implements Human{
    public void pringGender(){
        System.out.println("我是女性");
    }

    @Override
    public abstract void printColor();
}

其次我们来定义不同肤色的男人和女人

java 复制代码
public class BlackMan extends Man{
    @Override
    public void printColor() {
        System.out.println("我是黑人");
    }
}

public class BlackWoman extends Woman{
    @Override
    public void printColor() {
        System.out.println("我是黑人");
    }
}

public class WhiteMan extends Man{
    @Override
    public void printColor() {
        System.out.println("我是白人");
    }
}

public class WhiteWoman extends Woman{
    @Override
    public void printColor() {
        System.out.println("我是白人");
    }
}

public class YellowMan extends Man{
    @Override
    public void printColor() {
        System.out.println("我是黄种人");
    }
}

public class YellowWoman extends Woman{
    @Override
    public void printColor() {
        System.out.println("我是黄种人");
    }
}

下面我们定义工厂抽象基类

java 复制代码
public abstract class AbstractHumanFactory {
    //创建男人
    public abstract Man createMan();
    //创人女人
    public abstract Woman createWoman();
}

基类创建完成,下面实现各个人种工厂类,继承实现工厂抽象基类

java 复制代码
public class BlackHumanFactory extends AbstractHumanFactory{
    @Override
    public Man createMan() {
        return new BlackMan();
    }

    @Override
    public Woman createWoman() {
        return new BlackWoman();
    }
}
java 复制代码
public class WhiteHumanFactory extends AbstractHumanFactory{
    @Override
    public Man createMan() {
        return new WhiteMan();
    }

    @Override
    public Woman createWoman() {
        return new WhiteWoman();
    }
}
java 复制代码
public class YellowHumanFactory extends AbstractHumanFactory{

    @Override
    public Man createMan() {
        return new YellowMan();
    }

    @Override
    public Woman createWoman() {
        return new YellowWoman();
    }
}

抽象工厂所有类定义完成,下面使用测试Demo测试

java 复制代码
   @Test
    public void test3(){
        com.lym.framework.factory.demofour.AbstractHumanFactory factory = null;
        //创建黑人工厂
        factory = new com.lym.framework.factory.demofour.BlackHumanFactory();
        //创建黑人男人
        Man blackMan = factory.createMan();
        blackMan.printColor();
        blackMan.pringGender();
        //创建黑人女人
        Woman blackWoman = factory.createWoman();
        blackWoman.printColor();
        blackWoman.pringGender();

        //创建白人工厂
        factory = new com.lym.framework.factory.demofour.WhiteHumanFactory();
        //创建白人男人
        Man whithMan = factory.createMan();
        whithMan.printColor();
        whithMan.pringGender();
        //创建白人女人
        Woman whiteWoman = factory.createWoman();
        whiteWoman.printColor();
        whiteWoman.pringGender();

        //创建黄人工厂
        factory = new com.lym.framework.factory.demofour.YellowHumanFactory();
        //创建黄人男人
        Man yellowMan = factory.createMan();
        yellowMan.printColor();
        yellowMan.pringGender();
        //创建黄人女人
        Woman yellowWoman = factory.createWoman();
        yellowWoman.printColor();
        yellowWoman.pringGender();
    }

测试结果如下

java 复制代码
我是黑人
我是男性
我是黑人
我是女性
我是白人
我是男性
我是白人
我是女性
我是黄种人
我是男性
我是黄种人
我是女性

Process finished with exit code 0

下面我们总结一下抽象工厂模式的优缺点

优点:

1、一致性保证:确保创建的产品对象属于同一产品族

2、易于切换产品族:只需要更换具体工厂即可

3、复核开闭原则:增加新产品族容易,只需要扩展具体工厂

4、封装性好:隐藏产品创建细节

增加固定类型产品的不同具体工厂比较方便,例如:现在要创建一个绿皮人,只需要再创建一个绿皮人的工厂继承抽象工厂就可以了

缺点:

1、扩展困难:增加新产品等级结构复杂

2、类数量多:每新增一个产品族就需要多个类

3、灵活性受限:难以混合不同产品族的对象

适用场景

--产品族存在:系统需要创建多个产品族中的产品对象

--产品约束关系:产品之间有约束关系,需要一起使用

--界面风格统一:需要创建具有相同主题的UI组件

--数据库访问层:不同数据库的连接和命令对象

与其他模式的关系

--工厂方法模式:抽象工厂通常使用工厂方法来实现

--建造者模式:都关注对象创建,但是抽象工厂关注产品族

--原型模式:可以结合使用,原型作为工厂创建的对象

--桥接模式:有时可以互换使用

相关推荐
HL_风神6 小时前
C++设计模式浅尝辄止
c++·设计模式
会员果汁7 小时前
22.设计模式-享元模式(Flyweight)
设计模式·哈希算法·享元模式
亓才孓9 小时前
[设计模式]单例模式的懒汉式写法
单例模式·设计模式
小码过河.11 小时前
设计模式——访问者模式
设计模式·访问者模式
Engineer邓祥浩12 小时前
设计模式学习(21) 23-19 备忘录模式
学习·设计模式·备忘录模式
亓才孓12 小时前
[设计模式]单例模式饿汉式写法
单例模式·设计模式
代码丰13 小时前
设计模式:不再手动 set DTO,采用 Builder 模式
设计模式
老蒋每日coding13 小时前
AI Agent 设计模式系列(二十一)—— 探索和发现设计模式
人工智能·设计模式
茶本无香1 天前
设计模式之八: 适配器模式解释及应用
java·设计模式·适配器模式