工厂模式--摆脱你日复一日new对象却依旧单身的苦恼!

Posted MeloJun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工厂模式--摆脱你日复一日new对象却依旧单身的苦恼!相关的知识,希望对你有一定的参考价值。

前言

每每谈及到Java,就不免会想到一个悲伤的事实:你是否每天都在new对象,却依然坚守在单身岗上屹立不倒。(所谓面向对象编程hhh),这篇来学一下工厂模式,摆脱new对象的苦恼!

知识点

传统工厂

  • 抽象类和子类们
  • 生产和使用放在一起了没有分离开,使用时传名字,然后来生产相应的产品
public class OrderPizza {

	// 构造器
	public OrderPizza() {
		Pizza pizza = null;
		String orderType; // 订购披萨的类型
		
			orderType = getType();
			if (orderType.equals("greek")) {
				pizza = new GreekPizza();
				pizza.setName(" 希腊披萨 ");
			} else if (orderType.equals("cheese")) {
				pizza = new CheesePizza();
				pizza.setName(" 奶酪披萨 ");
			} else if (orderType.equals("pepper")) {
				pizza = new PepperPizza();
				pizza.setName("胡椒披萨");
			} else {
				break;
			}
			//输出pizza 制作过程
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
			
	}

改进的思路分析分析

  • 修改代码可以接受,但是如果我们在其它的地方也有创建Pizza的代码,就意味着,也需要修改,而创建Pizza的代码,往往有多处。
  • 思路:把创建Pizza对象封装到一个工厂类中,这样我们有新的Pizza种类时,只需要修改该工厂类就好,其它有创建到Pizza对象的代码就不需要修改了.->简单工厂模式

简单工厂模式(传产品名字然后if-else)

一个超级工厂,负责生产所有种类的产品

  • 在传统工厂的基础上,通过将产品创建的过程封装成一个工厂类,实现生产和使用分离开

接口类/抽象类

package com.melo.design.工厂模式.简单工厂模式;

public interface Shape {

    void draw();
}

子类产品

package com.melo.design.工厂模式.简单工厂模式;

public class Circle implements Shape{
    @Override
    public void draw() {
        System.out.println("Circle");
    }
}

工厂类

package com.melo.design.工厂模式.简单工厂模式;

public class ShapeFactory {

    public static Shape getShape(String shape){
        if("Circle".equals(shape)){
            return new Circle();
        }else if("Triangle".equals(shape)){
            return new Triangle();
        }
        return null;
    }
}

调用方

package com.melo.design.工厂模式.简单工厂模式;

public class Main {

    public static void main(String[] args) {
        Shape circle = ShapeFactory.getShape("Circle");
        circle.draw();
    }
}

缺点

总而言之,简单工厂模式就是让一个工厂类承担构建所有对象的职责。调用者需要什么产品,让工厂生产出来即可。它的弊端也显而易见:

  • 一是如果需要生产的产品过多,此模式会导致工厂类过于庞大,承担过多的职责,变成超级类。当苹果生产过程需要修改时,要来修改此工厂。梨子生产过程需要修改时,也要来修改此工厂。也就是说这个类不止一个引起修改的原因。违背了单一职责原则
  • 二是当要生产新的产品时,必须在工厂类中添加新的分支。而开闭原则告诉我们:类应该对修改封闭。我们希望在添加新功能时,只需增加新的类,而不是修改既有的类,所以这就违背了开闭原则

工厂方法模式

  • 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。
  • 工厂方法让类的实例化推迟到子类中进行!!!

原本简单工厂是一个工厂,负责生产所有的产品,现在要改成每个对象对应一个工厂,一个工厂只负责生产一个产品

优点

  • 这样我们就解决了上文所述的单一职责问题,每个工厂只负责生产一个产品
  • 同时也解决了开闭原则,每次需要新增一个产品的时候,我们只需要新增一个工厂类就好,而不需要去修改原来的工厂类

缺点

  • 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

每个产品对应一个工厂类,然后同一类的产品,比如都是水果类,则再抽象一个水果工厂出来,具体的工厂类去实现他的create方法

MyDemo

水果接口

package com.melo.mydesign.Factory.FactoryMethod.Product;

//产品只关心使用,不关心创建
public interface Fruit {
    void eat();
}

水果具体子类

package com.melo.mydesign.Factory.FactoryMethod.Product;

public class Apple implements Fruit {
    @Override
    public void eat() {
        System.out.println("吃苹果");
    }
}
package com.melo.mydesign.Factory.FactoryMethod.Product;

public class Pear implements Fruit {

    @Override
    public void eat() {
        System.out.println("吃梨子");
    }
}

水果工厂接口

package com.melo.mydesign.Factory.FactoryMethod.Factory;

import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit;

public interface FruitFactory {
    Fruit createFruit();
}

具体水果工厂实现子类

package com.melo.mydesign.Factory.FactoryMethod.Factory;

import com.melo.mydesign.Factory.FactoryMethod.Product.Apple;
import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit;

public class AppleFactory implements FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Apple();
    }
}
package com.melo.mydesign.Factory.FactoryMethod.Factory;

import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit;
import com.melo.mydesign.Factory.FactoryMethod.Product.Pear;

public class PearFactory implements FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Pear();
    }
}

具体使用

package com.melo.mydesign.Factory.FactoryMethod;

import com.melo.mydesign.Factory.FactoryMethod.Factory.AppleFactory;
import com.melo.mydesign.Factory.FactoryMethod.Factory.FruitFactory;
import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit;

public class Consumer {

    public static void main(String[] args) {
        //使用者不需要知道是哪个类在生产,面对的都是 FruitFactory 这个接口
        FruitFactory appleFactory = new AppleFactory();
        Fruit apple = appleFactory.createFruit();
        apple.eat();
    }

}

抽象工厂模式

  • 工厂方法模式,随着产品越来越多,会产生越来越多的产品类和产品工厂,能不能把一类产品,抽离出来变成一个产品家族呢?

这意味着不再是每一个产品就对应一个产品工厂了
而是一类产品,对应一个产品类工厂


以菜鸟的为例子(感觉比较权威一点)

UML

  • 首先从使用者的角度,要生产一个产品,一开始肯定是先找到那个产品所在的产品类工厂

如何找到产品类工厂?相当于产品类工厂也需要有人来创造他,又是处理多个产品的工厂类,我们叫他FactoryProducer

  • 然后拿到具体的产品类工厂了,就要生产具体的产品,处理方式同上(if-else)
    • 剩下的就是产品和父类产品了,具体实现代码见下方

可以看到Shape工厂要负责多个Shape了,就回归到简单工厂,一个工厂处理多个产品(需要传字符串名字然后if-else)

抽象工厂和具体产品类工厂(注意需要把工厂类的方法都定义出来)

具体实现看子类

  • 可以看到Shape产品类工厂,也得实现Color的方法,只不过return null罢了

同时,FactoryProducer也得处理多个,既要处理Shape也要处理Color

具体使用

MyDemo

抽象产品类工厂

package com.melo.mydesign.Factory.AbstractFactory.Factory;

import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit;

public interface AbstractFactory {
    Fruit createFruit(String fruitName);

    Car createCar(String carName);
}

具体产品类工厂--Car

package com.melo.mydesign.Factory.AbstractFactory.Factory;

import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Audi;
import com.melo.mydesign.Factory.AbstractFactory.Product.Car.BMW;
import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit;


public class CarFactory implements AbstractFactory{
    @Override
    public Fruit createFruit(String fruitName) {
        return null;
    }

    public Car createCar(String carName){
        if(carName.equalsIgnoreCase("BMW")){
            return new BMW();
        }else if(carName.equalsIgnoreCase("Audi")) {
            return new Audi();
        }
        return null;
    }
}

具体产品类工厂--Fruit

package com.melo.mydesign.Factory.AbstractFactory.Factory;

import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Pear;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Apple;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit;

public class FruitFactory implements AbstractFactory {
    public Fruit createFruit(String fruitName){
        if(fruitName.equalsIgnoreCase("Apple")){
            return new Apple();
        }else if(fruitName.equalsIgnoreCase("Pear")) {
            return new Pear();
        }
        return null;
    }

    @Override
    public Car createCar(String carName) {
        return null;
    }
}

FactoryProducer--负责生产产品类工厂的对象

package com.melo.mydesign.Factory.AbstractFactory.Factory;

public class FactoryProducer {

    public static AbstractFactory produceFactory(String factoryName){
        if(factoryName.equalsIgnoreCase("Fruit")){
            return new FruitFactory();
        }else if (factoryName.equalsIgnoreCase("Car")){
            return new CarFactory();
        }
        return null;
    }
}

Car类产品接口

package com.melo.mydesign.Factory.AbstractFactory.Product.Car;

//产品只关心使用,不关心创建
public interface Car {
    void eat();
}

Car类产品实现类

package com.melo.mydesign.Factory.AbstractFactory.Product.Car;

public class BMW implements Car {
    @Override
    public void eat() {
        System.out.println("宝马");
    }
}

Fruit类产品

package com.melo.mydesign.Factory.AbstractFactory.Product.Fruit;

//产品只关心使用,不关心创建
public interface Fruit {
    void eat();
}

Fruit类实现类

package com.melo.mydesign.Factory.AbstractFactory.Product.Fruit;


import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit;

public class Pear implements Fruit {

    @Override
    public void eat() {
        System.out.println("吃梨子");
    }
}

消费者

package com.melo.mydesign.Factory.AbstractFactory;

import com.melo.mydesign.Factory.AbstractFactory.Factory.AbstractFactory;
import com.melo.mydesign.Factory.AbstractFactory.Factory.FactoryProducer;
import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car;

public class Consumer {
    public static void main(String[] args) {
        AbstractFactory carFactory = FactoryProducer.produceFactory("Car");
        Car bmw = null;
        if (carFactory != null) {
            bmw = carFactory.createCar("BMW");
        }
        if (bmw != null) {
            bmw.eat();
        }
    }
}

缺点

  • 不再符合开闭原则了,因为本质是由简单工厂去升级而来的,又回归到了一个产品类工厂,需要处理多个产品的问题,**就需要if-else了 **

总结

  • 一个小小的工厂模式,就把前边学到的几大原则: 开闭原则 ,依赖倒转原则(善用抽象接口而不是具体实现) 体现得淋漓尽致.
    • 产品一旦多起来,就要抽离出一个抽象的产品类接口,让子类去实现他,使用者只关心抽象,而不关心具体的实现,不需要知道具体的类名,想生成苹果就直接 Fruit apple = new Apple(); 而不用 Apple apple = new Apple();
    • 而如果生产的过程变得复杂起来,比如苹果还需要各种处理,就需要将创建的过程封装起来,不暴露给使用者,这时就需要用到专门的工厂类来进行包装了,外界只需要从工厂里边拿就好了,传一个简单的"苹果"字符串,这就演变到了简单工厂模式了
  • 再然后我们发现一个简单工厂类,名曰简单,但是却要处理各种各样的产品,每次新增一个产品,都得去修改if-else代码块,不符合开闭原则
    • 由此引入了 工厂方法模式 让每一个产品就去对应有一个产品工厂,专门的工厂来生产产品,一个工厂只负责一个产品的生成,满足了单一职责原则,同时每次新增产品,只需要多加一个产品工厂就好了,无需修改原来的工厂,又解决了开闭原则的问题
  • 然而,随着产品数量越来越大,单纯一个工厂负责一个产品的话,工厂的数量也许会越来越多,而且,这些产品之前可能存在某些联系,比如都是水果类,那我们何不抽离出一个水果工厂,来生产各式各样的水果呢

看到这里可能有细心的读者就发现了,一个工厂又要去负责生产多个产品了,那似乎又回到了简单工厂模式,不符合开闭原则和单一职责了,是的,抽象工厂模式其实就是简单工厂的升级版而已!

参考

如何学习设计模式? - 力扣(LeetCode)的回答 - 知乎 https://www.zhihu.com/question/308850392/answer/1324509357

别再到处 new 对象了,试试 3 大工厂模式,真香!!

你还在到处 new 对象吗?

单身狗:我没对象,new 怎么了?

new 对象本身是没问题的,但也不能全部 new 关键字走天下,其实有更好的方式,合适的时候可以试试工厂模式,代码会更优雅。

什么是工厂模式?

顾名思义,工厂模式中的 "工厂" 指的是创建对象的工厂,它提供了一种创建对象的最佳方式,也就是工厂模式。

工厂模式的好处是这些对象不需要暴露自身的创建过程,统一由工厂模式进行创建和提供,隐藏了创建细节,避免了错误的创建对象的形式,也减少了重复创建冗余代码。

一般情况下,工厂模式可以细分为三类:

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

不过在设计模式权威书籍《设计模式:可复用面向对象软件的基础》一书中,简单工厂模式只是工厂方法模式的一个特例而已。

所以,从权威的角度说,工厂模式只分为: 工厂模式抽象工厂模式 两大类。

但不管白猫黑猫,能抓老鼠的就是好猫,设计模式亦是如此,不管怎么分类,这些模式都是程序员们历年过往经验的浓缩,都是值得学习和借鉴的。

所以,本文栈长从细分的角度带大家来实战下这三个工厂设计模式。

1、简单工厂

比如 XX 公司是做支付的,公司有几大类的客户:电商商户、银行客户、代理商……

创建这些客户的时候我们可以用简单工厂模式来实现看看。

新建客户基类:

可以把所有客户公共的信息放到一个客户基类中,比如:客户名、客户类型等,所有的客户继承这个抽象基类。

/**
 * 客户
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public abstract class Customer {

    /**
     * 客户名称
     */
    private String name;

    /**
     * 客户类型
     */
    private String type;

}

新建电商商户类:

/**
 * 商户
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
@Data
@ToString(callSuper = true)
public class Merchant extends Customer {

    /**
     * 合同类型
     */
    private int contractType;

    /**
     * 结算周期(天)
     */
    private int settmentDays;

    public Merchant(String name, String type) {
        super(name, type);
    }
}

新建银行客户类:

/**
 * 银行客户
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
@Data
@ToString(callSuper = true)
public class BankPartner extends Customer {

    /**
     * 银行编码
     */
    private String code;

    /**
     * 银行地址
     */
    private String address;

    public BankPartner(String name, String type) {
        super(name, type);
    }
}

新建代理商类:

/**
 * 代理商
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
@Data
@ToString(callSuper = true)
public class Agent extends Customer {

    /**
     * 代理周期
     */
    private int period;

    /**
     * 代理产品
     */
    private int[] products;

    public Agent(String name, String type) {
        super(name, type);
    }
}

新增简单工厂类:

新建一个简单工厂,提供一个公共静态方法,根据不同的客户类型创建不同的客户。

/**
 * 客户简单工厂
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class CustomerFactory {

    private static Merchant createMerchant(String type, String name) {
        return new Merchant(type, name);
    }

    private static BankPartner createBankPartner(String type, String name) {
        return new BankPartner(type, name);
    }

    private static Agent createAgent(String type, String name) {
        return new Agent(type, name);
    }

    public static Customer create(String type, String name) {
        if ("M".equals(type)) {
            return createMerchant(type, name);
        } else if ("B".equals(type)) {
            return createBankPartner(type, name);
        } else if ("A".equals(type)) {
            return createAgent(type, name);
        }
        return null;
    }

}

新建测试类:

/**
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class Test {

    public static void main(String[] args) {
        Customer merchant = CustomerFactory.create("M", "Java技术栈商户");
        System.out.println(merchant);

        Customer bankPartner = CustomerFactory.create("B", "Java技术栈银行客户");
        System.out.println(bankPartner);

        Customer agent = CustomerFactory.create("A", "Java技术栈代理商");
        System.out.println(agent);
    }

}

输出结果:

本节教程所有实战源码已上传到这个仓库:

https://github.com/javastacks/javastack

可以看出简单工厂的使用很简单,就是耦合性太高了。

第一,对象和基类之间是基于继承的。

第二,工厂类耦合了不同对象的创建,如果对象类型不是固定或者经常变动的,就要频繁修改工厂类,比如我现在要再加一种客户,就必须要改动工厂类,不符开闭原则。

所以,简单工厂只适用于固定类型对象的创建。

2、工厂方法

工厂方法就是为某类产品提供一个工厂接口,然后为每个产品提供一个工厂实现类。

废话少说,我们将简单工厂的示例用工厂方法再改造一下。

新建工厂方法接口:

/**
 * 工厂方法客户接口
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public interface CustomerFactory {

    Customer create(String type, String name);

}

新建商户工厂实现类:

/**
 * 商户工厂
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class MerchantFactory implements CustomerFactory {

    @Override
    public Customer create(String type, String name) {
        return new Merchant(type, name);
    }

}

新建银行客户工厂实现类:

/**
 * 银行客户工厂
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class BankPartnerFactory implements CustomerFactory {

    @Override
    public Customer create(String type, String name) {
        return new BankPartner(type, name);
    }

}

新建代理商工厂实现类:

/**
 * 代理商工厂
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class AgentFactory implements CustomerFactory {

    @Override
    public Customer create(String type, String name) {
        return new Agent(type, name);
    }

}

新建测试类:

/**
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class Test {

    public static void main(String[] args) {
        System.out.println("------工厂模式-工厂方法------");

        CustomerFactory merchantFactory = new MerchantFactory();
        Customer merchant = merchantFactory.create("M", "Java技术栈商户");
        System.out.println(merchant);

        CustomerFactory bankPartnerFactory = new BankPartnerFactory();
        Customer bankPartner = bankPartnerFactory.create("B", "Java技术栈银行客户");
        System.out.println(bankPartner);

        CustomerFactory agentFactory  = new AgentFactory();
        Customer agent = agentFactory.create("A", "Java技术栈代理商");
        System.out.println(agent);
    }

}

输出结果:

本节教程所有实战源码已上传到这个仓库:

https://github.com/javastacks/javastack

可以看出,工厂方法也是挺简单易用的,耦合性问题也解决了,每增加一个产品就新增一个产品工厂实现类就行了,扩展性非常好。

但也有一个问题,如果产品非常多,那势必会造成工厂实现类泛滥,另外一种可怕的场景就是,如果涉及到工厂接口变更,工厂实现类的维护简直就是一种恶梦。

3、抽象工厂

工厂方法中一个工厂只能创建一个对象,如果现在每次创建客户的时候都需要同时创建一份客户扩展资料,那就可以考虑使用抽象工厂。

新建客户扩展基类:

可以把所有客户公共的扩展信息放到一个客户扩展基类中,比如:客户曾用名、客户扩展说明等,所有的客户继承这个扩展抽象基类。

/**
 * 客户扩展
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
@Data
@NoArgsConstructor
public abstract class CustomerExt {

    /**
     * 客户曾用名
     */
    private String formerName;

    /**
     * 客户扩展说明
     */
    private String note;

}

新建商户扩展类:

/**
 * 商户
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
@Data
@ToString(callSuper = true)
public class MerchantExt extends CustomerExt {

    /**
     * 介绍人
     */
    private int introduceName;

    /**
     * 介绍人电话
     */
    private String introduceTel;

}

新建银行客户扩展类:

/**
 * 银行客户扩展
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
@Data
@ToString(callSuper = true)
public class BankPartnerExt extends CustomerExt {

    /**
     * 分行个数
     */
    private int branchCount;

    /**
     * ATM个数
     */
    private int atmCount;

}

新建代理商扩展类:

/**
 * 商户
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
@Data
@ToString(callSuper = true)
public class AgentExt extends CustomerExt {

    /**
     * 来源
     */
    private String source;

    /**
     * 资质
     */
    private String certification;

}

新建抽象工厂接口:

/**
 * 抽象工厂客户接口
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public interface CustomerFactory {

    Customer createCustomer(String type, String name);

    CustomerExt createCustomerExt();

}

新建商户工厂实现类:

/**
 * 商户工厂
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class MerchantFactory implements CustomerFactory {

    @Override
    public Customer createCustomer(String type, String name) {
        return new Merchant(type, name);
    }

    @Override
    public CustomerExt createCustomerExt() {
        return new MerchantExt();
    }

}

新建银行客户工厂实现类:

/**
 * 银行客户工厂
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class BankPartnerFactory implements CustomerFactory {

    @Override
    public Customer createCustomer(String type, String name) {
        return new BankPartner(type, name);
    }

    @Override
    public CustomerExt createCustomerExt() {
        return new BankPartnerExt();
    }

}

新建代理商工厂实现类:

/**
 * 代理商工厂
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class AgentFactory implements CustomerFactory {

    @Override
    public Customer createCustomer(String type, String name) {
        return new Agent(type, name);
    }

    @Override
    public CustomerExt createCustomerExt() {
        return new AgentExt();
    }

}

新建测试类:

/**
 * @author: 栈长
 * @from: 公众号Java技术栈
 */
public class Test {

    public static void main(String[] args) {
        System.out.println("------工厂模式-抽象工厂------");

        CustomerFactory merchantFactory = new MerchantFactory();
        Customer merchant = merchantFactory.createCustomer("M", "Java技术栈商户");
        CustomerExt merchantExt = merchantFactory.createCustomerExt();
        System.out.println(merchant);
        System.out.println(merchantExt);

        CustomerFactory bankPartnerFactory = new BankPartnerFactory();
        Customer bankPartner = bankPartnerFactory.createCustomer("B", "Java技术栈银行客户");
        CustomerExt bankPartnerExt = bankPartnerFactory.createCustomerExt();
        System.out.println(bankPartner);
        System.out.println(bankPartnerExt);

        CustomerFactory agentFactory = new AgentFactory();
        Customer agent = agentFactory.createCustomer("A", "Java技术栈代理商");
        CustomerExt agentExt = agentFactory.createCustomerExt();
        System.out.println(agent);
        System.out.println(agentExt);
    }

}

输出结果:

可以看出,抽象工厂和工厂方法十分类似,只不过抽象工厂里面只生产一个对象,而抽象工厂可以生产多个对象。

抽象工厂缺点也很明显,第一就是和工厂方法一样工厂类非常多,第二就是扩展非常麻烦,比如我现在要为每个客户类型再加一份客户特殊资料,那所有涉及到抽象工厂的工厂类都要改,是不是要疯了。。

总结

如果有多个属于同一种类型的类,可以考虑使用工厂模式,统一提供生成入口,能从一定程度上解耦,扩展方便,也不用再到处 new 对象了。

但话又说回来,从示例可以看出,如果使用或者设计不当也会带来维护上的工作量。

本节教程所有实战源码已上传到这个仓库:

https://github.com/javastacks/javastack

好了,今天的分享就到这里了,后面栈长我会更新其他设计模式的实战文章,公众号Java技术栈第一时间推送。Java技术栈《设计模式》系列文章陆续更新中,请大家持续关注哦!

最后,觉得我的文章对你用收获的话,动动小手,给个在看、转发,原创不易,栈长需要你的鼓励。

版权申明:本文系公众号 "Java技术栈" 原创,原创实属不易,转载、引用本文内容请注明出处,禁止抄袭、洗稿,请自重,尊重大家的劳动成果和知识产权,抄袭必究。

近期热文推荐:

1.1,000+ 道 Java面试题及答案整理(2021最新版)

2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!

3.阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式发布,全新颠覆性版本!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

以上是关于工厂模式--摆脱你日复一日new对象却依旧单身的苦恼!的主要内容,如果未能解决你的问题,请参考以下文章

别再到处 new 对象了,试试 3 大工厂模式,真香!!

别再到处 new 对象了,试试 3 大工厂模式,真香!!

面试官:工厂方法模式是什么?

PHP工厂模式

JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)

JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)