工厂模式包括:

  • 简单工厂
  • 工厂方法
  • 抽象工厂
  • 将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。工厂模式都是实现创建者和调用者分离,下面开始逐一介绍:

  • 简单工厂模式
  • 模式UML类图

    角色分析

    • Factory:工厂角色
    • Product:抽象产品角色
    • ConcreteProduct:具体产品角色
    工厂角色(Creator) 是简单工厂模式的核心,它负责实现创建所有具体产品类的实例。工厂类可以被外界直接调用,创建所需的产品对象。
    抽象产品角色(Product) 是所有具体产品角色的父类,它负责描述所有实例所共有的公共接 口 。
    具体产品角色(Concrete Product) 继承自抽象产品角色,一般为多个,是简单工厂模式的创建目标。工厂类返回的都是该角色的某一具体产品。

    示例程序:通过汽车工厂生产汽车(奔驰和奥迪两种车型),消费者(客户端)只需要与汽车工厂联系(依赖)

    示意图

    代码实现

    package Factory;
    interface Car{
        void run();
    }
    class Aodi implements Car{
        @Override
        public void run() {
            System.out.println("我是奥迪汽车...");
        }
    }
    class Benchi implements Car{
        @Override
        public void run() {
            System.out.println("我是奔驰汽车...");
        }
    }
    class CarFactory{
        static public Car createCar(String name) {
            Car car = null;
            if(name.equals("奥迪")) {
                car = new Aodi();
            }else if(name.equals("奔驰")) {
                car = new Benchi();
            }
            return car;
        }
    }
    /**
     * @author Moti
     * @Time 2019年9月21日
     */
    public class Main {
        public static void main(String[] args) {
            Car car = CarFactory.createCar("奔驰");
            car.run();
        }
    }

    分析简单工厂模式的优缺点

  • 优点
  • 工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。

  • 缺点
  • 由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。违反开闭原则

    当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;

    这些缺点在工厂方法模式中得到了一定的克服。

  • 工厂方法模式
  • 模式UML类图

    每一个产品都有自己独立的工厂

    角色分析

    • 抽象产品(Product)
    • 具体产品(Concrete Product)
    • 抽象工厂(Factory)
    • 具体工厂(Concrete Factory)
    抽象产品(Product) 具体产品的父类
    描述具体产品的公共接口
    具体产品(Concrete Product) 抽象产品的子类;工厂类创建的目标类
    描述生产的具体产品
    抽象工厂(Factory) 具体工厂的父类
    描述具体工厂的公共接口
    具体工厂(Concrete Factory) 抽象工厂的子类;被外界调用描述具体工厂;实现FactoryMethod工厂方法创建产品的实例

    示例程序:通过奥迪汽车工厂或者奔驰汽车工厂生产汽车,消费者(客户端)只需要与汽车工厂联系(依赖)

    示意图

    实例程序UML类图

    代码实现

    1. 汽车的抽象类

    package AbstractFactory;
    /**
     * 定义汽车的抽象类
     * @author Moti
     * @Time 2019年9月27日 下午3:04:23
     */
    public abstract class Car {
        public abstract void run();
    }

    2. 奥迪汽车类

    package AbstractFactory;
    /**
     * 定义奥迪车,继承抽象类Car实现run方法
     * @author Moti
     * @Time 2019年9月27日 下午3:06:10
     */
    public class Aodi extends Car {
        @Override
        public void run() {
            System.out.println("我是奥迪车..滴滴滴..");
        }
    }

    3. 奔驰汽车类

    package AbstractFactory;
    /**
     * 定义奔驰车,继承抽象类Car实现run方法
     * @author Moti
     * @Time 2019年9月27日 下午3:07:29
     */
    public class Benchi extends Car {
        @Override
        public void run() {
            System.out.println("我是奔驰车..滴滴滴..");
        }
    }

    4. 抽象汽车工厂的接口

    package AbstractFactory;
    /**
     * 汽车工厂的接口,将具体实例的生成交给子类
     * @author Moti
     * @Time 2019年9月27日 下午3:08:35
     */
    public interface CarFactory {
        Car createCar();
    }

    5. 奥迪汽车工厂的类,实现了抽象汽车工厂接口

    package AbstractFactory;
    /**
     * 定义奥迪车的工厂
     * @author Moti
     * @Time 2019年9月27日 下午3:09:53
     */
    public class AodiCarFactory implements CarFactory {
        @Override
        public Car createCar() {
            return new Aodi();
        }
    }

    6. 奔驰汽车工厂的类,实现了抽象汽车工厂接口

    package AbstractFactory;
    /**
     * 定义奔驰车的工厂
     * @author Moti
     * @Time 2019年9月27日 下午3:10:57
     */
    public class BenchiCarFactory implements CarFactory {
        @Override
        public Car createCar() {
            return new Benchi();
        }
    }

    7. 客户端调用

    package AbstractFactory;
    /**
     * @author Moti
     * @Time 2019年9月27日 下午3:12:45
     */
    public class Client {
        public static void main(String[] args) {
            CarFactory carFactory1 = new AodiCarFactory();
            CarFactory carFactory2 = new BenchiCarFactory();
            Car car1 = carFactory1.createCar();
            Car car2 = carFactory2.createCar();
            car1.run();
            car2.run();
        }
    }

    分析工厂方法模式的优缺点

  • 优点
  • 用户只需要关心所需产品对应的工厂,无需关心创建细节,甚至无需知道具体产品类名;所有的具体工厂类都具有同一抽象父类;符合开闭原则,新增产品只需要添加工厂类和具体产品,无需修改代码,扩展性好;

  • 缺点
  • 添加一个新的产品,系统中类的个数增加,导致增加了系统的复杂性,有更多的类需要编译和运行,会增加系统性能的开销;由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度;

  • 抽象工厂模式
  • 前言

    1. 抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类
    2. 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
    3. 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
    4. 将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

    产品等级:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。

    产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。

    模式UML类图

    这里,1号工厂(ConcreteFactory1)可以生产A,B,C三种产品(ConcreteProductA,B,C)
    同样,2号工厂也可以生产A,B,C三种产品

    那么1号工厂生产的这三种产品构成一个产品族,2号工厂生产的这三种产品也构成一个产品族.

    1号工厂生产的A产品和2号工厂生产的A产品构成一个产品等级
    1号工厂生产的B产品和2号工厂生产的B产品 构成一个产品等级
    1号工厂生产的C产品和2号工厂生产的C产品 构成一个产品等级

    角色分析

    • 抽象产品(Product)
    • 具体产品(Concrete Product)
    • 抽象工厂(Factory)
    • 具体工厂(Concrete Factory)
    抽象产品(Product) 具体产品的父类
    描述具体产品的公共接口
    具体产品(Concrete Product) 抽象产品的子类;工厂类创建的目标类
    描述生产的具体产品
    抽象工厂(Factory) 具体工厂的父类
    描述具体工厂的公共接口
    具体工厂(Concrete Factory) 抽象工厂的子类;被外界调用描述具体工厂;实现抽象工厂中创建产品的实例

    示例程序:获得三种电子元件(RAM,CPU,Mouse),有日本工厂和中国工厂,这两个工厂都可以生产这三种电子元件

    注意:这里日本工厂生产的所有产品构成一个产品族,中国工厂生产的所有产品也构成一个产品族,共两个产品族.示例程序中出现了两种RAM,两种CPU,两种Mouse(分别来自中国工厂和日本工厂),这些同种商品分类构成一个产品等级,也就是说有三个产品等级.

    示例程序UML类图

    代码实现

    1.抽象产品和具体产品

    //设备接口(产品的抽象)
    public interface Device {
        String getDeviceName();
    }
    //RAM(具体的产品)
    public class RAM implements Device {
        private String factoryName;
        public RAM(String factoryName) {
            this.factoryName = factoryName;
        }
        @Override
        public String getDeviceName() {
            return "获得"+factoryName+"生产的RAM";
        }
    }
    //CPU(具体的产品)
    public class CPU implements Device {
        private String factoryName;
        public CPU(String factoryName) {
            this.factoryName = factoryName;
        }
        @Override
        public String getDeviceName() {
            return "获得"+factoryName+"生产的CPU";
        }
    }
    //Mouse(具体的产品)
    public class Mouse implements Device {
        private String factoryName;
        public Mouse(String factoryName) {
            this.factoryName = factoryName;
        }
        @Override
        public String getDeviceName() {
            return "获得"+factoryName+"生产的Mouse";
        }
    }

    2.抽象工厂和具体工厂

    //抽象工厂
    public interface DeviceFactory {
        Device createCPU();
        Device createARM();
        Device createMouse();
    }
    //具体工厂
    public class ChinaFactoy implements DeviceFactory {
        @Override
        public Device createCPU() {
            return new CPU("中国");
        }
        @Override
        public Device createARM() {
            return new RAM("中国");
        }
        @Override
        public Device createMouse() {
            return new Mouse("中国");
        }
    }
    //具体工厂
    public class JapanFactory implements DeviceFactory{
        @Override
        public Device createCPU() {
            return new CPU("日本");
        }
        @Override
        public Device createARM() {
            return new RAM("日本");
        }
        @Override
        public Device createMouse() {
            return new Mouse("日本");
        }
    }

    3.客户端Client

    public class Client {
        public static void main(String[] args) {
            DeviceFactory factory = new JapanFactory();
            Device device = factory.createMouse();
            String string = device.getDeviceName();
            System.out.println(string);
        }
    }

    分析抽象工厂模式的优缺点

  • 优点
  • 分离了具体的类。客户通过抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,它们不出现在客户代码中。

    易于交换产品系列。一个具体工厂类只在初始化时出现一次,这使得改变一个应用的具体工厂变得很容易,只需改变具体的工厂即可使用不同的产品配置。

    有利于产品的一致性。当一个系列的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要,而抽象工厂很容易实现这一点。 

  • 缺点
  • 难以支持新种类的产品。因为抽象工厂接口确定了可以被创建的产品集合(产品族),所以难以扩展抽象工厂以生产新种类的产品。

    最后修改日期:2020-07-13

    作者

    留言

    撰写回覆或留言

    发布留言必须填写的电子邮件地址不会公开。