【设计模式】-创建型模式-第2章第2讲-【工厂模式】

简介: 【设计模式】-创建型模式-第2章第2讲-【工厂模式】

目录

场景描叙:

1、简单工厂模式

1.1、静态工厂模式

1.2、 使用反射机制进行类注册的简单工厂模式

1.3、使用 newInstance 方法进行类注册的简单工厂模式

2、工厂方法模式

2.1、案例场景:假设有一个汽车工厂,目前只生产两种车型,小型跑车和大型家用车。顾客决定买小还是大型。

2.2、这时候,我们需要拓展业务,增加卡车类的生产,那我们可以创建一个卡车工厂(TruckFactory)。

3、抽象工厂模式

结尾:

场景描叙:

比如小汽车(Car)和 卡车 (Truck)都属于车辆(Vehicle),那我们实例化对象时,就需要分别实例化两个对象。

Vehicle vehicle = new Car();

Vehicle vehicle = new Truck();

以上的代码就存在两个问题:

1)类应该保持对扩展开放,对修改关闭(开闭原则);

每增加新的类造成主要代码修改会打破开闭原则。

2)每个类应该只有一个发生变化的原因(单一职责原则);

而主类除了自身固有功能还要负责实例化 vehicle 对象,这种行为打破了单一职责原则。

所以这种情况下就需要一种更好的设计方案。我们可以增加一个新类来负责实例化 vehicle 对象,称之为简单工厂模式。
1、简单工厂模式

工厂模式用于实现逻辑的封装,并通过公共接口提供对象的实例化服务,在添加新类时只需要做少量修改即可。

通俗点儿就是封装一个抽象工厂类,实现对象的实例化。

简单工厂的实现描叙如 图 1-1 所示:
d0c4d14badf443ec8d1437be8868a737.png

图 1-1


1.1、静态工厂模式

我们创建一个抽象 Vehicle 类和继承自它的三个具体类:Bike、Car 和 Truck

  package com.zhaoyanfei.designpattern.simpleFactory;
    
   public abstract class Vehicle {
    
   }

   package com.zhaoyanfei.designpattern.simpleFactory;
    
   public class Bike extends Vehicle {
    
   }

   package com.zhaoyanfei.designpattern.simpleFactory;
    
   public class Car extends Vehicle {
    
   }

   package com.zhaoyanfei.designpattern.simpleFactory;
    
   public class Truck extends Vehicle {
    
   }

这里,我们写一个简单的工厂类用来创建 Vehicle 实例。工厂类(静态工厂类)代码如下:

    package com.zhaoyanfei.designpattern.simpleFactory;
     
    public class VehicleFactory {
        
        public enum VehicleType
        {
            Bike,Car,Truck;
        }
        public static Vehicle create(VehicleType type) {
            if(type.equals(VehicleType.Bike)) 
            return new Bike();
            if(type.equals(VehicleType.Car)) 
            return new Car();
            if(type.equals(VehicleType.Truck)) 
            return new Truck();
            else return null;
        }
    }

通过上面代码示例,我们可以看到工厂类逻辑非常简单,只负责抽象类 (Vehicle) 类的实例化,符合单一职责原则,用户只需要调用 Vehicle 接口,这么做可以减少耦合,符合依赖倒置原则;但是增加一个新的 Vehicle 类时,需要对 VehicleFactory 工厂类进行修改,就打破了开闭原则。

我们可以改进这种简单工厂模式,使得注册的新类在使用时才被实例化,从而保证其对扩展开放,对修改关闭。

具体实现方式有以下两种:

1)使用反射机制注册产品类对象和实例化。

2)注册产品对象并向每个产品添加 newInstanse 方法,该方法返回与自身类型相同的新实例。
1.2、 使用反射机制进行类注册的简单工厂模式

这里,我们在工厂类中需要用 map 对象来保存产品 ID 及其对应的类:

然后增加一个注册新 Vehicle 类的方法

    package com.zhaoyanfei.designpattern.simpleFactory;
     
    import java.util.HashMap;
    import java.util.Map;
     
    public class VehicleFactory {
        
        public enum VehicleType
        {
            Bike,Car,Truck;
        }
        public static Vehicle create(VehicleType type) {
            if(type.equals(VehicleType.Bike)) 
            return new Bike();
            if(type.equals(VehicleType.Car)) 
            return new Car();
            if(type.equals(VehicleType.Truck)) 
            return new Truck();
            else return null;
        }
        //工厂类中需要用 map 对象来保存产品 ID 及其对应的类
        private Map<String,Class> registeredProducts = new HashMap<String,Class>();
        //然后增加一个注册新 Vehicle 类的方法
        public void registerVehicle(String vehicleId,Class vehicelClass) {
            registeredProducts.put(vehicleId, vehicelClass);
        }
        //构造方法如下所示:
        public Vehicle createVehicle(String type) throws InstantiationException, IllegalAccessException {
            Class productClass = registeredProducts.get(type);
            return (Vehicle) productClass.newInstance();
        }
    }

上面代码中,我们可以看到反射实例化对象时,会有异常抛出。所以在某些情况下,反射机制并不适用。另外,反射机制也会降低程序的运行效率,在对性能要求很高的场景下应该避免使用这种机制。
1.3、使用 newInstance 方法进行类注册的简单工厂模式

前面我们用的反射机制来实现新 Vehicle 类的实例化。如果要避免使用反射机制,可以使用注册新 Vehicle 类的类似工厂类,不再将类添加到 map 对象中,而是将要注册的每种对象实例添加其中。每个产品类都能够创建自己的实例。

1)首先在基类 Vehicle 中添加一个抽象方法:

    package com.zhaoyanfei.designpattern.simpleFactory;
     
    public abstract class Vehicle {
     
        abstract public Vehicle newInstance();
     
    }

2)此时,大家都知道,子类必须实现基类中声明的抽象方法:

Bike、Car 和 Truck 都需要实现 newInstance()方法,每个产品类创建自己的实例。

    package com.zhaoyanfei.designpattern.simpleFactory;
     
    public class Bike extends Vehicle {
     
        @Override
        public Vehicle newInstance() {
            return new Bike();
        }
     
    }

3)在工厂类中,更改 map 用于保存对象的 ID 及其对应的 Vehicle 对象:

    package com.zhaoyanfei.designpattern.simpleFactory;
     
    import java.util.HashMap;
    import java.util.Map;
     
    public class VehicleFactory {
        
        public enum VehicleType
        {
            Bike,Car,Truck;
        }
        public static Vehicle create(VehicleType type) {
            if(type.equals(VehicleType.Bike)) 
            return new Bike();
            if(type.equals(VehicleType.Car)) 
            return new Car();
            if(type.equals(VehicleType.Truck)) 
            return new Truck();
            else return null;
        }
        /**
         * 反射机制
         */
        //工厂类中需要用 map 对象来保存产品 ID 及其对应的类
    //    private Map<String,Class> registeredProducts = new HashMap<String,Class>();
    //    //然后增加一个注册新 Vehicle 类的方法
    //    public void registerVehicle(String vehicleId,Class vehicelClass) {
    //        registeredProducts.put(vehicleId, vehicelClass);
    //    }
    //    //构造方法如下所示:
    //    public Vehicle createVehicle(String type) throws InstantiationException, IllegalAccessException {
    //        Class productClass = registeredProducts.get(type);
    //        return (Vehicle) productClass.newInstance();
    //    }
        
        /**
         * 注册产品对象,并向每个产品添加 newInstance 方法,该方法返回与自身类型相同的新实例
         */
        private Map<String,Vehicle> registeredProducts = new HashMap<String,Vehicle>();
        //然后增加一个注册新 Vehicle 类的方法
        public void registerVehicle(String vehicleId,Vehicle vehicle) {
            registeredProducts.put(vehicleId, vehicle);
        }
        //构造方法如下所示:
        public Vehicle createVehicle(String type) {
            Vehicle productClass = registeredProducts.get(type);
            return productClass.newInstance();
        }
    }

2、工厂方法模式

工厂方法模式(FACTORY METHOD)是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂;具体工厂;抽象产品;具体产品

工厂方法模式是在静态工厂模式上的改进。工厂类被抽象化,用于实例化特定产品类的代码被转移到实现抽象方法的子类中。这样就不需要修改就可以扩展工厂类。实现如 图2-1:

64f57d99599640419578c9f37425197d.png

2.1、案例场景:假设有一个汽车工厂,目前只生产两种车型,小型跑车和大型家用车。顾客决定买小还是大型。

1)首先我们需要创建一个 Vehicle 类和两个子类,子类分别为 SportCar 和 SedanCar。

    package com.zhaoyanfei.designpattern.factorymethod;
     
    public class Vehicle {
        String color;
        
        public void setColor(String color) {
            this.color = color;
        }
     
    }
    package com.zhaoyanfei.designpattern.factorymethod;
     
    public class SportCar extends Vehicle {
     
    }
    package com.zhaoyanfei.designpattern.factorymethod;
     
    public class SedanCar extends Vehicle {
     
    }

2)创建抽象工厂类,此类中不包含任何创建新实例的代码:

    package com.zhaoyanfei.designpattern.factorymethod;
     
     
    public abstract class VehicleFactory {
     
        protected  abstract Vehicle createVehicle(String item);
        
        public Vehicle orderVehicle(String size,String color) {
            Vehicle vehicle = createVehicle(size);
            vehicle.setColor(color);
            return vehicle;
        }
    }

3)增加汽车实例化代码,我们创建 VehicleFactory 的子类

    package com.zhaoyanfei.designpattern.factorymethod;
     
    public class CarFactory extends VehicleFactory {
     
        @Override
        protected Vehicle createVehicle(String size) {
            if(size.equals("small")) {
                return new SportCar();
            }else if(size.equals("large")) {
                return new SedanCar();
            }else {
                return null;
            }
        }
        
    }

4)客户端,我们只需要创建工厂类并创建订单:

    package com.zhaoyanfei.designpattern.factorymethod;
     
    public class TestMethodFactory {
     
        public static void main(String[] args) {
            VehicleFactory carFactory = new CarFactory();
            Vehicle orderVehicle = carFactory.orderVehicle("large", "green");
            System.out.println("类名:"+orderVehicle.getClass().getName()+"颜色:"+orderVehicle.color);
        }
    }

运行后可以看到如下输出:

1cb03ee37def47e2a6bfa723408cbeb3.png

2.2、这时候,我们需要拓展业务,增加卡车类的生产,那我们可以创建一个卡车工厂(TruckFactory)。

    package com.zhaoyanfei.designpattern.factorymethod;
     
    public class TruckFactory extends VehicleFactory {
     
        @Override
        protected Vehicle createVehicle(String size) {
            if(size.equals("small")) {
                return new SmallTruck();
            }else if(size.equals("large")) {
                return new LargeTruck();
            }else {
                return null;
            }
        }
        
    }

我们就可以这样来创建卡车订单了:

    VehicleFactory truckFactory = new TruckFactory();
    Vehicle orderVehicle = truckFactory.orderVehicle("large", "blue");

3、抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是工厂方法模式的扩展版本。它不再是创建单一类型的对象,而是创建一系列相关联的对象,如果说工厂方法模式中只包含一个抽象产品类,那么抽象工厂模式则包含多个抽象产品类。所以说工厂方法模式只是抽象工厂模式的一种特例。

抽象工厂设计模式的实现如图 3-1 所示:

6c83cab5765845b3a5b65702bfe626a1.png


图 3-1


抽象工厂模式由以下类组成:

AbstractFactory (抽象工厂类):抽象类,用于声明创建不同类型产品的方法。它针对不同的抽象产品类都有对应的创建方法。
ConcreteFactory (具体工厂类):具体类,用于实现抽象工厂基类中声明的方法。针对每个系列的产品都有一个对应的具体工厂类。
AbstractProduct(抽象产品类):对象所需要的基本接口或类。一簇相关产品类由来自不同层级的相似产品类组成。ProductA1 和 ProductB1 来自第一个类簇,由 ConcreteFactory1 实例化。ProductA2 和 ProductB2 来自第二个类簇,由 ConcreteFactory2 实例化。

结尾:

工厂的模式的核心就是右工厂类来负责合适对象的创建。如果工厂类很复杂,比如同时服务于多种类型的对象或工厂,也可以根据前面内容修改相应的代码。

下一节,分享建造者模式……

相关文章
|
1月前
|
设计模式 Java
【设计模式】工厂模式(定义 | 特点 | Demo入门讲解)
【设计模式】工厂模式(定义 | 特点 | Demo入门讲解)
50 2
|
2月前
|
设计模式
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
这篇文章详细解释了工厂模式,包括简单工厂、工厂方法和抽象工厂三种类型。每种模式都通过代码示例展示了其应用场景和实现方法,并比较了它们之间的差异。简单工厂模式通过一个工厂类来创建各种产品;工厂方法模式通过定义一个创建对象的接口,由子类决定实例化哪个类;抽象工厂模式提供一个创建相关或依赖对象家族的接口,而不需要明确指定具体类。
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
|
3月前
|
设计模式 存储 负载均衡
【五】设计模式~~~创建型模式~~~单例模式(Java)
文章详细介绍了单例模式(Singleton Pattern),这是一种确保一个类只有一个实例,并提供全局访问点的设计模式。文中通过Windows任务管理器的例子阐述了单例模式的动机,解释了如何通过私有构造函数、静态私有成员变量和公有静态方法实现单例模式。接着,通过负载均衡器的案例展示了单例模式的应用,并讨论了单例模式的优点、缺点以及适用场景。最后,文章还探讨了饿汉式和懒汉式单例的实现方式及其比较。
【五】设计模式~~~创建型模式~~~单例模式(Java)
|
3月前
|
设计模式 Java
Java 设计模式之谜:工厂模式与抽象工厂模式究竟隐藏着怎样的神奇力量?
【8月更文挑战第30天】在Java编程中,设计模式为常见问题提供了高效解决方案。工厂模式与抽象工厂模式是常用的对象创建型设计模式,能显著提升代码的灵活性、可维护性和可扩展性。工厂模式通过定义创建对象的接口让子类决定实例化哪个类;而抽象工厂模式则进一步提供了一个创建一系列相关或相互依赖对象的接口,无需指定具体类。这种方式使得系统更易于扩展和维护。
42 1
|
3月前
|
设计模式 算法 开发者
深入理解工厂模式与策略模式:设计模式的灵活应用
深入理解工厂模式与策略模式:设计模式的灵活应用
|
3月前
|
设计模式 XML 存储
【三】设计模式~~~创建型模式~~~抽象工厂模式(Java)
文章详细介绍了抽象工厂模式,这是一种创建型设计模式,用于提供一个接口以创建一系列相关或相互依赖的对象,而不指定它们具体的类。通过代码示例和结构图,文章展示了抽象工厂模式的动机、定义、结构、优点、缺点以及适用场景,并探讨了如何通过配置文件和反射机制实现工厂的动态创建。
【三】设计模式~~~创建型模式~~~抽象工厂模式(Java)
|
3月前
|
设计模式 XML 存储
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
文章详细介绍了工厂方法模式(Factory Method Pattern),这是一种创建型设计模式,用于将对象的创建过程委托给多个工厂子类中的某一个,以实现对象创建的封装和扩展性。文章通过日志记录器的实例,展示了工厂方法模式的结构、角色、时序图、代码实现、优点、缺点以及适用环境,并探讨了如何通过配置文件和Java反射机制实现工厂的动态创建。
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
|
3月前
|
设计模式 XML Java
【一】设计模式~~~创建型模式~~~简单工厂模式(Java)
文章详细介绍了简单工厂模式(Simple Factory Pattern),这是一种创建型设计模式,用于根据输入参数的不同返回不同类的实例,而客户端不需要知道具体类名。文章通过图表类的实例,展示了简单工厂模式的结构、时序图、代码实现、优缺点以及适用环境,并提供了Java代码示例和扩展应用,如通过配置文件读取参数来实现对象的创建。
【一】设计模式~~~创建型模式~~~简单工厂模式(Java)
|
3月前
|
设计模式 uml C语言
设计模式----------工厂模式之简单工厂模式(创建型)
这篇文章详细介绍了简单工厂模式,包括其定义、应用场景、UML类图、通用代码实现、运行结果、实际应用例子,以及如何通过反射机制实现对象创建,从而提高代码的扩展性和维护性。
设计模式----------工厂模式之简单工厂模式(创建型)
|
3月前
|
设计模式 uml
设计模式-------------工厂模式之工厂方法模式(创建型)
工厂方法模式是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而实现类的实例化推迟到子类中进行,提高了系统的灵活性和可扩展性。

热门文章

最新文章

  • 1
    C++一分钟之-设计模式:工厂模式与抽象工厂
    42
  • 2
    《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
    46
  • 3
    C++一分钟之-C++中的设计模式:单例模式
    54
  • 4
    《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
    38
  • 5
    《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
    62
  • 6
    Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
    57
  • 7
    Java面试题:设计模式在并发编程中的创新应用,Java内存管理与多线程工具类的综合应用,Java并发工具包与并发框架的创新应用
    41
  • 8
    Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
    50
  • 9
    Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
    106
  • 10
    Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
    78