创建型模式:工厂方法模式

什么是工厂方法模式

工厂方法模式是一种创建型设计模式,它定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类中进行,从而将对象的创建与使用过程分离,使系统更加灵活。

为什么需要工厂方法模式

当一个类不知道它所必须创建的对象的类时,或者一个类希望由其子类来指定它所创建的对象时,工厂方法模式就派上了用场。例如,一个跨平台的UI框架需要创建不同操作系统下的按钮控件,但具体创建哪种按钮取决于运行环境。

工厂方法模式解决了"在不指定具体类的情况下创建对象"的问题。

工厂方法模式的核心实现

// 产品接口
public interface Product {
    void operation();
}

// 具体产品A
public class ConcreteProductA implements Product {
    @Override
    public void operation() {
        System.out.println("产品A的操作");
    }
}

// 具体产品B
public class ConcreteProductB implements Product {
    @Override
    public void operation() {
        System.out.println("产品B的操作");
    }
}

// 创建者接口
public abstract class Creator {
    // 工厂方法
    public abstract Product createProduct();
    
    // 某些使用产品的操作
    public void someOperation() {
        // 调用工厂方法创建产品
        Product product = createProduct();
        // 使用产品
        product.operation();
    }
}

// 具体创建者A
public class ConcreteCreatorA extends Creator {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

// 具体创建者B
public class ConcreteCreatorB extends Creator {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

工厂方法模式的关键点

  1. 产品接口:定义工厂方法所创建的对象的接口
  2. 具体产品:实现产品接口的具体类
  3. 创建者接口/抽象类:声明工厂方法,返回产品类型的对象
  4. 具体创建者:重写工厂方法以返回特定的产品实例

实际应用示例:物流运输系统

下面通过一个物流运输系统的例子来展示工厂方法模式的应用:

// 运输工具接口
public interface Transport {
    void deliver(String goods);
}

// 卡车运输
public class Truck implements Transport {
    @Override
    public void deliver(String goods) {
        System.out.println("通过卡车运输" + goods + ",走陆路");
    }
}

// 轮船运输
public class Ship implements Transport {
    @Override
    public void deliver(String goods) {
        System.out.println("通过轮船运输" + goods + ",走水路");
    }
}

// 飞机运输
public class Airplane implements Transport {
    @Override
    public void deliver(String goods) {
        System.out.println("通过飞机运输" + goods + ",走空路");
    }
}

// 物流抽象类
public abstract class Logistics {
    // 工厂方法
    public abstract Transport createTransport();
    
    // 规划运输
    public void planDelivery(String goods) {
        System.out.println("开始规划运输...");
        // 通过工厂方法创建运输工具
        Transport transport = createTransport();
        System.out.println("安排货物装载...");
        // 使用运输工具
        transport.deliver(goods);
        System.out.println("运输完成!");
    }
}

// 公路物流
public class RoadLogistics extends Logistics {
    @Override
    public Transport createTransport() {
        return new Truck();
    }
}

// 海运物流
public class SeaLogistics extends Logistics {
    @Override
    public Transport createTransport() {
        return new Ship();
    }
}

// 空运物流
public class AirLogistics extends Logistics {
    @Override
    public Transport createTransport() {
        return new Airplane();
    }
}

如何使用工厂方法模式

public class LogisticsDemo {
    public static void main(String[] args) {
        // 客户端代码
        System.out.println("======= 运输电子产品 =======");
        
        // 根据距离、成本等因素选择物流方式
        Logistics logistics;
        String transportType = "air"; // 可能来自配置或用户选择
        
        // 根据运输类型选择具体的物流类
        if (transportType.equals("road")) {
            logistics = new RoadLogistics();
        } else if (transportType.equals("sea")) {
            logistics = new SeaLogistics();
        } else {
            logistics = new AirLogistics();
        }
        
        // 使用选定的物流安排运输
        // 注意客户端代码只与抽象类交互,不直接使用具体产品类
        logistics.planDelivery("智能手机100部");
        
        System.out.println("\n======= 运输食品 =======");
        // 更换物流方式
        logistics = new RoadLogistics();
        logistics.planDelivery("新鲜水果10吨");
    }
}

运行结果

======= 运输电子产品 =======
开始规划运输...
安排货物装载...
通过飞机运输智能手机100部,走空路
运输完成!

======= 运输食品 =======
开始规划运输...
安排货物装载...
通过卡车运输新鲜水果10吨,走陆路
运输完成!

工厂方法模式的常见应用场景

  1. GUI框架:不同操作系统下创建不同外观的控件
  2. 数据库连接器:支持多种数据库系统
  3. 多格式文件解析器:处理不同格式的文件
  4. 支付系统:集成多种支付方式
  5. 日志记录框架:支持多种日志输出方式
  6. 跨平台应用:适配不同平台的功能实现
  7. 游戏角色创建:生成不同类型的游戏角色

工厂方法模式的优点

  1. 单一职责原则:将产品创建代码与使用代码分离
  2. 开闭原则:可以引入新产品而无需修改现有代码
  3. 灵活性:客户端代码与具体产品类解耦
  4. 可测试性:便于对产品进行单元测试

工厂方法模式的缺点

  1. 类爆炸:每增加一种产品,就需要增加一个具体工厂类
  2. 复杂度增加:引入了额外的抽象层次
  3. 继承限制:工厂角色通常由子类实现,不适合需要组合而非继承的场景

工厂方法与简单工厂的区别

简单工厂将所有产品的创建集中在一个工厂类中,通过条件判断创建不同产品:

public class SimpleFactory {
    public static Transport createTransport(String type) {
        if (type.equals("truck")) {
            return new Truck();
        } else if (type.equals("ship")) {
            return new Ship();
        } else if (type.equals("airplane")) {
            return new Airplane();
        }
        throw new IllegalArgumentException("未知运输类型");
    }
}

而工厂方法模式将产品创建委托给子类,更符合开闭原则,但需要创建更多类。

工厂方法模式小结

工厂方法模式通过将对象的创建延迟到子类进行,实现了创建与使用的分离。它适用于当一个类无法预知它所必须创建的对象的类,或希望由子类来指定创建的对象的情况。

这种模式在现代框架和库中被广泛使用,理解工厂方法模式有助于我们设计出更灵活、可维护的代码。在面向对象编程中,工厂方法是最基本也是最常用的设计模式之一。

你可能感兴趣的:(Java,设计模式,工厂方法模式,java,开发语言)