5.创建型模式(工厂)

1.工厂模式简述

  • 基本思想:凡是需要生成复杂对象的地方,都可以尝试考虑工厂模式来代替
    • 复杂对象:类的构造函数参数过多等对类的构造有影响的情况
  • 定义:一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类中。(创建与使用分离)
    • 产品:被创建的对象
    • 工厂:创建产品的对象

2.简单工厂模式

  • 创建实例的方法常为静态方法(静态工厂方法模式)
  • 应用场景: 产品种类较少的情况

优点:
1.工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
2.客户端无需知道所创建具体产品的类名,只需知道参数即可。
3.也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。

缺点:
1.简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
2.使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
3.系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
4.简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。

2.1结构与实现

image

  1. 简单工厂SimpleFactory:简单工厂模式的核心,负责实现创建所有实例的内部逻辑。其创建产品类的方法可直接被外界调用以创建所需产品对象。
  2. 抽象产品Product:简单工厂创建的所有对象的父类,负责描述所有实例公有的公共接口
  3. 具体产品ConcreteProduct:简单工厂模式的创建目标

示例:

//简单工厂
public class EasyFactory {
	public static void main(String[] args) {
		Product a = EasyFactory.makeProduct(1);
		a.show();
	}

	public static Product makeProduct(int kind) {
		if (kind == 1) {
			return new Concrete1();
		} else {
			return new Concrete2();
		}
	}
}

//抽象产品
interface Product{
	void show();
}

//具体产品1
class Concrete1 implements Product {
	@Override
	public void show() {
		System.out.println("产品1");
	}
}

//具体产品2
class Concrete2 implements Product {
	@Override
	public void show() {
		System.out.println("产品2");
	}
}

3.工厂模式

  • 基于简单工厂模式,使系统在不修改源代码情况下引进新产品,符合开闭原则
  • 优点
    1. 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
    2. 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
    3. 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
  • 缺点
    1. 类的个数容易过多,增加复杂度
    2. 增加了系统的抽象性和理解难度
    3. 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
  • 应用场景:
    1. 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
    2. 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
    3. 客户不关心创建产品的细节,只关心产品的品牌

3.1 结构

  1. 抽象工厂:提供创建产品的接口,调用者通过其访问具体工厂的工厂方法以创建产品
  2. 具体工厂:实现抽象工厂中的抽象方法,完成具体产品创建
  3. 抽象产品:定义产品规范,描述产品主要特性和功能
  4. 具体产品:实现了抽象产品所定义的接口,由具体工厂创建,同具体工厂之间一一对应。
    image

3.2 实现

  • 创造可生成猪/马的工厂
点击查看工厂示例
public class Factory {
    public static void main(String[] args) {
        CreateAnimal factory1 = new CreateHorse();
        Animal horse1 = factory1.getAnimal();
        horse1.show();
    }
}

//抽象产品,提供产品接口
interface Animal {
    void show();
}

//具体产品1:马
class Horse implements Animal {
    @Override
    public void show() {
        System.out.println("Horse!");
    }
}

//具体产品2:猪
class Pig implements Animal {
    @Override
    public void show() {
        System.out.println("Pig!");
    }
}

//抽象工厂,提供产品生成方法
interface CreateAnimal {
    Animal getAnimal();
}

//具体工厂1:生成马
class CreateHorse implements CreateAnimal{
    @Override
    public Animal getAnimal() {
        return new Horse();
    }
}

//具体工厂2:生成猪
class CreatePig implements CreateAnimal {
    @Override
    public Animal getAnimal() {
        return new Pig();
    }
}

4.抽象工厂模式

  • 产品工厂与产品族解析
    image

  • 定义: 一种为访问类提供一个创建一组相关或相互依赖对象的接口,访问类无需指定索要产品具体类就得到同族不同等级的产品。

  • 需满足条件

    1. 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品
    2. 系统一次只可能消费某一族产品,即同族产品一起使用。
  • 优点:

    1. 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
    2. 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品族。
    3. 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。
  • 缺点:产品族中需增加一个新产品时,所有工厂类都需修改,增加抽象性和理解难度。

  • 适用场景

    1. 需创建的对象是一系列相互关联或相互依赖的产品族时(同一品牌的一系列产品)
    2. 系统中有多个产品族,但每次只使用其中某一族产品
    3. 系统中提供产品类库,且所有产品接口相同,客户端不依赖产品实例的创建细节和内部结构。
  • 当系统中只存在一个等级结构产品时,抽象工厂模式将退化为工厂方法模式。

4.1 结构

  1. 抽象工厂:提供创建产品的接口,包含多个创建产品的方法,可创建多个不同等级的产品
  2. 具体工厂:实现抽象工厂中多个抽象方法,完成具体产品创建
  3. 抽象产品:定义产品规范,描述产品主要特性和功能
  4. 具体产品,实现抽象产品角色定义的接口,由具体工厂创建,一个具体工厂对应多个具体产品

image

4.2具体实例

  • 创建农场模型,每个农场均有一种动物及其相关联植物。获取时需同时获取农场种动植物产品。
  • 猴子农场:猴子+水果 奶牛农场:牛+草
点击农场代码
public class AbstractFactory {
    public static void main(String[] args) {
        Farm farm = new MonkeyFarm();
        //获取工厂后无需获知产品细节
        Animals David = farm.newAnimals();
        Plants fruit1 = farm.newPlant();
        David.show();
        fruit1.show();

    }

}

interface Plants {
    void show();
}

class Grass implements Plants {
    @Override
    public void show() {
        System.out.println("Grass!");
    }
}

class Fruit implements Plants {
    @Override
    public void show() {
        System.out.println("Fruit");
    }
}

//抽象动物产品
interface Animals {
    void show();
}

//具体产品--奶牛
class Cow implements Animals {
    @Override
    public void show() {
        System.out.println("Cow!");
    }
}

//具体产品-单例猴子
class Monkey implements Animals {
    private static final Monkey instance = new Monkey();

    private Monkey(){};

    public static Monkey getInstance() {
        return instance;
    }

    @Override
    public void show() {
        System.out.println("Monkey!");
    }
}

//抽象工厂-农场:提供动物及植物
interface Farm {
    Plants newPlant();

    Animals newAnimals();
}

//具体奶牛工厂
class CowFarm implements Farm{
    @Override
    public Plants newPlant() {
        return new Grass();
    }

    @Override
    public Animals newAnimals() {
        return new Cow();
    }
}

//具体Monkey工厂
class MonkeyFarm implements Farm{
    @Override
    public Plants newPlant() {
        return new Fruit();
    }

    @Override
    public Animals newAnimals() {
        return Monkey.getInstance();
    }
}

5 工厂模式总结

  1. 简单工厂:不提供工厂的抽象接口,由一个工厂实例静态方法创建产品
  2. 工厂:基于简单工厂提供工厂的抽象接口
  3. 抽象工厂:基于工厂对一族产品进行工厂封装,实现一个工厂生产一族所有产品
posted @ 2021-10-10 13:51  rttrti  阅读(103)  评论(0编辑  收藏  举报