工厂模式包括:

  • 简单工厂
  • 工厂方法
  • 抽象工厂

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

  • 简单工厂模式

模式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);
    }
}

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

  • 优点

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

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

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

  • 缺点

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

12-22 06:33
查看更多