说起工厂,我们第一反应是制作什么东西的吧~。在现实生活中,工厂 , 就是用于生成一些特定事物的厂商。
回到我们此处说的工厂模式上,什么是工厂模式呢 , 顾名思义,就是生成我们的对象的类就会称成为工厂。
我们这里说的工厂模式 包括了三种工厂模式 : 分别是 简单工厂 、工厂方法、抽象工厂。
一、简单工厂
1、简单工厂定义:
简单工厂也称为静态工厂。是一种创建型模式。在简单工厂中,可以根据传入参数的不同返回不同类的对象实例。简单工厂是一个专门的工厂类,用来创建不同其他类的实例对象。这些实例对象通常他们的父类是同一个抽象类或者接口。
2、我们为什么要使用简单工厂呢?他可以带给我们什么好处呢?
在通常的做法中,我们会将对象创建的代码写在具体的业务代码中(即使用对象的代码写到一块)。这样会存在一个问题就是——>假设使用对象的地方有多个类使用,且创建对象的过程相似。在多个使用对象的类中都需要写一遍重复的构建对象的代码。
当我们不关心对象的产生方式时,我们就可以使用简单工厂模式。
3、我们可以先看下类图
普通类图
简单工厂类图
对于简单工厂来说。如果在版本迭代的过程中,产品类(Product)初始化的相关逻辑需要更改,我们只需要修改简单工厂类中的逻辑即可。不需要修改原有的业务逻辑类,也不会产生修改此业务逻辑造成原有类中其他部分出现问题。
4、代码示例
抽象产品。
package com.starcpdk.factory.simpleFactory;
public abstract class Food {
String name;
public Food() {
}
public Food(String name) {
this.name = name;
}
public abstract void eat(String foodName);
public abstract void back(String foodName);
public abstract void cut(String foodName);
public abstract void paper(String foodName);
}
具体产品1
package com.starcpdk.factory.simpleFactory;
public class Bread extends Food{
public Bread(String name) {
super(name);
}
public Bread() {
}
@Override
public void eat(String foodName) {
System.out.println(super.name + "吃" + foodName);
}
@Override
public void back(String foodName) {
System.out.println(super.name + "烤" + foodName);
}
@Override
public void cut(String foodName) {
System.out.println(super.name + "切" + foodName);
}
@Override
public void paper(String foodName) {
System.out.println(super.name + "准备" + foodName);
}
}
具体产品2
package com.starcpdk.factory.simpleFactory;
public class Rice extends Food{
public Rice(String name) {
super(name);
}
public Rice() {
}
@Override
public void eat(String foodName) {
System.out.println(super.name + "吃" + foodName + "嘎嘎香");
}
@Override
public void back(String foodName) {
System.out.println(super.name + "烤"+ foodName + "嘎嘎旺");
}
@Override
public void cut(String foodName) {
System.out.println(super.name + "切" + foodName + "嘎嘎爽");
}
@Override
public void paper(String foodName) {
System.out.println(super.name + "准备"+ foodName +"嘎嘎愉快");
}
}
简单工厂
package com.starcpdk.factory.simpleFactory;
public class SimpleFactory {
private SimpleFactory() {
}
private static Food food;
public static Food createFood(String foodType) {
if (foodType.equals("rice")) {
food = new Rice("张三");
} else if (foodType.equals("bread")) {
food = new Bread("李四");
}
return food;
}
}
客户端
package com.starcpdk.factory.simpleFactory;
public class Main {
public static void main(String[] args) {
Food bread = SimpleFactory.createFood("bread");
bread.eat("法师面包");
Food rice = SimpleFactory.createFood("rice");
rice.eat("牛奶米饭");
}
}
5、使用场景
我们在不关注实例的创建过程时,就可以使用简单工厂模式。将类创建实例的过程交给工厂类去创建,我们只需需要去向工厂类索要实例即可。
主要是面向产品的创建,把创建由上层转移到下层。
如果项目的需求仅需new Product()能够满足后面的所有需求,依然使用最初的在业务层new 对象的方式即可。
二、工厂方法
简单工厂: 一个工厂统一负责所有产品的创建,一定会造成代码的可维护性差。相比简单工厂,工厂方法模式用一个工厂对应一类产品,创建的过程是一一对应的,也更加细颗粒度的创建,每当修改一个产品的创建过程,只需要修改产品对应的子类工厂即可。不会影响到其他产品的创建使用。将产品的创建过程延迟到工厂子类进行创建。
代码
package com.starcpdk.factory.factoryMethod;
public abstract class AbstractProduct {
public abstract void paper();
}
package com.starcpdk.factory.factoryMethod;
public class Product2 extends AbstractProduct{
@Override
public void paper() {
System.out.println("Product2 paper 。。。。");
}
}
package com.starcpdk.factory.factoryMethod;
public class Product1 extends AbstractProduct{
@Override
public void paper() {
System.out.println("Product1 paper 。。。。");
}
}
package com.starcpdk.factory.factoryMethod;
public abstract class AbstractFactory {
public abstract AbstractProduct createProduct();
}
package com.starcpdk.factory.factoryMethod;
public class Factory1 extends AbstractFactory{
@Override
public AbstractProduct createProduct() {
return new Product1();
}
}
package com.starcpdk.factory.factoryMethod;
public class Factory2 extends AbstractFactory{
@Override
public AbstractProduct createProduct() {
return new Product2();
}
}
package com.starcpdk.factory.factoryMethod;
public class Method {
public static void main(String[] args) {
AbstractFactory factory = new Factory1();
AbstractProduct product = factory.createProduct();
factory = new Factory2();
product = factory.createProduct();
product.paper();
product.paper();
}
}
总结:
相当于加了一层。在一个工厂类中生产各种产品,对单一产品的修改又或者增加产品都可能会影响到之前创建其他产品的逻辑。所以我们要加一层将创建产品的过程移至子类生产,每个工厂子类对应一个产品的生产。
- 产品的增加和删除不会影响到其他产品的产出
- 单个产品逻辑修改只需要在对应的工厂类修改即可,不需要动其他的工厂。
- 职责更加明确,方便维护。
三、抽象工厂
抽象工厂是基于产品族的概念建立的。我们先想一下工厂方法模式 是 一个子类工厂对应一个子类产品。
而我们的抽象工厂相当于是 一个子类工厂对应 一些子类产品。 而这些子类产品是一类产品。比如说 我们有一个产品 他有两类描述 即形状 和 颜色。那我们可以将形状划分为一族产品 , 将颜色划分为另外一族产品。这样我们就是相当于有两个工厂类。一个去负责创建形状类产品,一个负责创建 颜色类产品。假如后期我们这个产品又增加了一族产品叫 味道,那我们只需要增加一个工厂去负责创建味道 类的产品即可。
但是形状 有长方形,正方形,圆形等。颜色有蓝色, 绿色,红色等。
这类里面会有很多的产品。抽象工厂相当于是针对一类一类划分出的工厂。而工厂方法则是针对一个一个产品划分工厂。
其实工厂方法模式是抽象工厂模式的一种特殊体。即抽象工厂中只有一个产品族时,就是我们的工厂方法模式。
假设我们有两族产品 : 现代风格。古代风格。
每族产品有两个:椅子、桌子。
那我们就有两个抽象产品 分别是椅子、桌子,然后我们有椅子对应的实际产品,桌子对应的实际产品去分别继承椅子和桌子。然后我们有一个抽象工厂。这个抽象工厂有两个方法,一个创建椅子,一个创建桌子,具体创建什么桌子或者什么椅子根据传入的参数决定。然后我们有两个具体工厂,分别是现代工厂、古代工厂。都去实现这个抽象工厂,也就是说这两个工厂都会产生桌子和椅子。具体产生什么样的桌子和什么样的椅子,由传入的参数决定。
代码
package com.starcpdk.factory.abstractfactory;
public abstract class ProductA {
}
package com.starcpdk.factory.abstractfactory;
public class ProductA1 extends ProductA {
}
package com.starcpdk.factory.abstractfactory;
public class ProductA2 extends ProductA {
}
package com.starcpdk.factory.abstractfactory;
public abstract class ProductB {
}
package com.starcpdk.factory.abstractfactory;
public class ProductB1 extends ProductB {
}
package com.starcpdk.factory.abstractfactory;
public class ProductB2 extends ProductB {
}
package com.starcpdk.factory.abstractfactory;
public abstract class AbstractFactory {
public abstract ProductA createProductA();
public abstract ProductB createProductB();
}
package com.starcpdk.factory.abstractfactory;
public class Factory1 extends AbstractFactory{
@Override
public ProductA createProductA() {
return new ProductA1();
}
@Override
public ProductB createProductB() {
return new ProductB1();
}
}
package com.starcpdk.factory.abstractfactory;
public class Factory2 extends AbstractFactory{
@Override
public ProductA createProductA() {
return new ProductA2();
}
@Override
public ProductB createProductB() {
return new ProductB2();
}
}
package com.starcpdk.factory.abstractfactory;
public class Client {
public static void main(String[] args) {
Factory1 factory1 = new Factory1();
System.out.println(factory1.createProductA());
System.out.println(factory1.createProductB());
Factory2 factory2 = new Factory2();
System.out.println(factory2.createProductA());
System.out.println(factory2.createProductB());
}
}
总结:抽象工厂是增加一类产品方便,但是在单个产品的增加上不方便。
抽象工厂相当于是 配套的生产,增加一套容易,但是给每套增加一个就不容易了。如果要增加一个产品。即在抽象工厂中需要增加一个方法,那么实现抽象工厂的具体工厂就全部需要增加该方法。但是如果是增加一族产品,那就比较容易了 ,只需要增加一个工厂,去实现抽象工厂,然后这个工厂就会实现抽象工厂中的方法去创建对应的产品,创建的还是一大类产品,这一大类产品中的产品个数是不变的。还是一套。