设计模式-3.2工厂模式


⚡️ 工厂模式


  • 🛠️ 简单工厂模式:

    • 📌 描述: 建立一个实例化对象的类,该类中可以对多个对象进行实例化。
    • ⚠️ 注意: 它是一个具体的类,不是接口或抽象类。所有的对象创建请求都通过这个类的静态方法来完成。
  • 🛠️ 工厂方法模式:

    • 📌 描述: 定义了一个创建对象的抽象方法,由子类决定要实例化的类。
    • ⚠️ 注意: 在有新的类型的对象需要实例化时,只需增加相应的子类即可,无需修改已有的代码。
  • 🛠️ 抽象工厂模式:

    • 📌 描述: 定义了一个接口用于创建对象族,但无需明确指定具体类。
    • 📌 优点: 提供给客户端接口,避免了用户直接操作子类工厂。
    • ⚠️ 注意: 抽象工厂也将对象的实例化交给了具体的子类工厂,从而支持拓展。

⚠️ 注意: 工厂模式是面向对象编程中的一种设计模式,用于处理对象创建的问题,特别是当直接创建对象(使用new操作符)不便或不合适时。工厂模式将对象的创建和使用解耦,使得系统更加灵活、可扩展。


⚡️ 简单工厂模式(不属于GOF的23种经典设计模式)


🟢 结构

  • 抽象产品:

    • 📌 定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品:

    • 📌 实现或者继承了抽象产品的类。
  • 具体工厂:

    • 📌 提供了创建产品的方法,调用者通过它来获取新的产品对象。

🟢 优缺点

  • 优点:

    • 📌 封装了创建对象的过程,可以通过参数直接获取对象。
    • 📌 把对象的创建和业务逻辑层分开,便于扩展和维护。
    • ⚠️ 注意: 如果要实现新产品,直接修改工厂类即可,无需在原代码中进行大量修改。
  • 缺点:

    • 📌 增加新产品时需要修改工厂类的代码,这在一定程度上违背了“开闭原则”(软件实体应对扩展开放,对修改关闭)。

⚠️ 注意: 简单工厂模式适用于产品种类相对较少且不经常变动的场景,在复杂或频繁变动的产品需求场景下,可能就不太适用。


⚡️ 静态工厂模式(不属于GOF的23种经典设计模式)


🟢 特点

  • 静态方法:

    • 📌 工厂类中的方法通常定义为静态的,因此不需要创建工厂对象,直接通过工厂类名调用方法即可。
  • 创建对象:

    • 📌 通过调用工厂类中的静态方法来获取需要的对象。

🟢 优缺点

  • 优点:

    • 📌 无需创建工厂对象,直接调用方法即可,简单且方便。
    • 📌 通过静态方法封装对象创建的细节,使得调用者只关心如何使用对象。
  • 缺点:

    • 📌 由于静态方法无法继承和重写,所以静态工厂模式会限制子类的扩展和修改能力。
    • 📌 如果要增加新产品,仍然需要修改工厂类的代码,违背了“开闭原则”。

⚠️ 注意: 静态工厂模式适用于创建对象的过程稳定且不经常变动的场景。当产品种类或创建逻辑经常变动时,该模式可能会带来不便,因为每次变动都需要修改静态方法。


⚡️ 工厂方法模式


🟢 结构

  • 抽象工厂 (Abstract Factory):

    • 📌 提供了创建产品的接口。
    • 📌 调用者通过它访问具体工厂的工厂方法来创建产品。
  • 具体工厂 (Concrete Factory):

    • 📌 主要是实现抽象工厂中的抽象方法。
    • 📌 完成具体产品的创建。
  • 抽象产品 (Product):

    • 📌 定义了产品的规范。
    • 📌 描述了产品的主要特性和功能。
  • 具体产品(Concrete Product):

    • 📌 实现了抽象产品角色所定义的接口。
    • 📌 由具体工厂来创建,它与具体工厂之间是一一对应的。

🟢 优缺点

  • 优点:

    • 📌 用户只需知道具体工厂的名称,无须知道产品的具体创建过程。
    • 📌 当增加新的产品时,只需添加具体产品类和对应的具体工厂类,无需修改原有工厂,满足开闭原则。
  • 缺点:

    • 📌 每增加一个产品,就需增加一个具体产品类和一个对应的具体工厂类,增加了系统的复杂度。

⚠️ 注意: 工厂方法模式是面向对象设计的一种经典模式,它解决了代码与特定类的强耦合问题,使得增加新产品类别时,系统具有很好的可扩展性。


⚡️ 抽象工厂模式

在这里插入图片描述


🟢 结构

  • 抽象工厂 (Abstract Factory):

    • 📌 提供了创建产品的接口。
    • 📌 包含多个创建产品的方法,能够创建多个不同等级的产品。
  • 具体工厂 (Concrete Factory):

    • 📌 主要是实现抽象工厂中的抽象方法。
    • 📌 负责完成具体产品的创建。
  • 抽象产品 (Product):

    • 📌 定义了产品的规范。
    • 📌 描述了产品的主要特性和功能。
    • ⚠️ 注意: 抽象工厂模式有多个抽象产品。
  • 具体产品 (Concrete Product):

    • 📌 实现了抽象产品角色所定义的接口。
    • 📌 由具体工厂来创建。
    • ⚠️ 注意: 它与具体工厂之间是多对一的关系。

🟢 优缺点

  • 优点:

    • 📌 当一个产品族中的多个对象被设计成一起工作时,它能确保客户端始终只使用该产品族中的对象。
  • 缺点:

    • 📌 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改,增加了维护的复杂性。

⚠️ 注意: 抽象工厂模式用于创建一系列相关或互相依赖的对象,而不指定它们具体的类。它提供了一个接口,由子类决定实例化哪一个类,从而使得客户与实际创建对象的类解耦。


⚡️ 使用场景


📌 简单工厂

  • 产品等级结构:

    • 📌 简单工厂用于生产同一等级结构中的任意产品。
    • ⚠️ 注意: 不支持拓展增加产品。
  • 适用场合:

    • 📌 举例: 只有瑞幸咖啡工厂(唯一的生产工厂,即只有这一个等级结构)。
    • 📌 该工厂只生产两种固定类型的咖啡:美式咖啡拿铁咖啡
    • ⚠️ 注意: 如果需要增加新的咖啡种类,简单工厂模式可能不太适用,因为它不支持轻易地拓展增加产品。
      在这里插入图片描述
package com.study.notes.design.patterns.pattern.create.factory.simple_factory.bean;

/**
 * @version v1.0
 * @ClassName: Coffee
 * @Description: 咖啡类
 * @Author: lzq
 */
public abstract class Coffee {

    public abstract String getName();

    //加糖
    public void addSugar() {
        System.out.println("加糖");
    }

    //加奶
    public void addMilk() {
        System.out.println("加奶");
    }
}

package com.study.notes.design.patterns.pattern.create.factory.simple_factory.bean;


/**
 * @version v1.0
 * @ClassName: AmericanCoffee
 * @Description: 没事咖啡
 * @Author: lzq
 */
public class AmericanCoffee extends Coffee {

    @Override
    public String getName() {
        return "美式咖啡";
    }
}

package com.study.notes.design.patterns.pattern.create.factory.simple_factory.bean;


/**
 * @version v1.0
 * @ClassName: LatteCoffee
 * @Description: 拿铁咖啡
 * @Author: lzq
 */
public class LatteCoffee extends Coffee {

    @Override
    public String getName() {
        return "拿铁咖啡";
    }
}

package com.study.notes.design.patterns.pattern.create.factory.simple_factory.factory;

import com.study.notes.design.patterns.pattern.create.factory.simple_factory.bean.LatteCoffee;
import com.study.notes.design.patterns.pattern.create.factory.simple_factory.bean.AmericanCoffee;
import com.study.notes.design.patterns.pattern.create.factory.simple_factory.bean.Coffee;

/**
 * @version v1.0
 * @ClassName: SimpleCoffeeFactory
 * @Description: 简单咖啡工厂类,用来生产咖啡
 * @Author: lzq
 */
public class SimpleCoffeeFactory {

    public Coffee createCoffee(String type) {
        //声明Coffee类型的变量,根据不同类型创建不同的coffee子类对象
        Coffee coffee = null;
        if ("american".equals(type)) {
            coffee = new AmericanCoffee();
        } else if ("latte".equals(type)) {
            coffee = new LatteCoffee();
        } else {
            throw new RuntimeException("对不起,您所点的咖啡没有");
        }

        return coffee;
    }
}

package com.study.notes.design.patterns.pattern.create.factory.simple_factory.store;


import com.study.notes.design.patterns.pattern.create.factory.simple_factory.bean.Coffee;
import com.study.notes.design.patterns.pattern.create.factory.simple_factory.factory.SimpleCoffeeFactory;

/**
 * @version v1.0
 * @ClassName: CoffeeStore
 * @Description: TODO(一句话描述该类的功能)
 * @Author: lzq
 */
public class CoffeeStore {

    public Coffee orderCoffee(String type) {

        SimpleCoffeeFactory factory = new SimpleCoffeeFactory();
        //调用生产咖啡的方法
        Coffee coffee = factory.createCoffee(type);

        //加配料
        coffee.addMilk();
        coffee.addSugar();

        return coffee;
    }
}

package com.study.notes.design.patterns.pattern.create.factory.simple_factory;

import com.study.notes.design.patterns.pattern.create.factory.simple_factory.bean.Coffee;
import com.study.notes.design.patterns.pattern.create.factory.simple_factory.store.CoffeeStore;

/**
 * @version v1.0
 * @ClassName: Client
 * @Description: TODO(一句话描述该类的功能)
 * @Author: lzq
 */
public class Client {
    public static void main(String[] args) {
        //创建咖啡店类对象
        CoffeeStore store = new CoffeeStore();
        Coffee coffee = store.orderCoffee("latte");

        System.out.println(coffee.getName());
    }
}


📌 工厂方法

  • 产品等级结构:

    • 📌 用于生产同一等级结构中的固定产品。
    • ⚠️ 注意: 支持拓展增加产品。
  • 适用场合:

    • 📌 举例: 除了原有的瑞幸咖啡工厂,现在还增加了星巴克咖啡工厂(仍然是同一等级结构)。
    • 📌 无论是瑞幸还是星巴克,他们都生产两种固定类型的咖啡:美式咖啡拿铁咖啡
    • ⚠️ 注意: 由于采用工厂方法模式,当我们需要新增其他品牌的咖啡工厂时,可以很方便地拓展。
      在这里插入图片描述
package com.study.notes.design.patterns.pattern.create.factory.factory_method.factory;

import com.study.notes.design.patterns.pattern.create.factory.factory_method.bean.Coffee;

/**
 * @version v1.0
 * @ClassName: CoffeeFactory
 * @Description: CoffeeFactory : 抽象工厂
 * @Author: lzq
 */
public interface CoffeeFactory {

    //创建咖啡对象的方法
    Coffee createCoffee();
}

package com.study.notes.design.patterns.pattern.create.factory.factory_method.factory;

import com.study.notes.design.patterns.pattern.create.factory.factory_method.bean.AmericanCoffee;
import com.study.notes.design.patterns.pattern.create.factory.factory_method.bean.Coffee;

/**
 * @version v1.0
 * @ClassName: AmericanCoffeeFactory
 * @Description: 美式咖啡工厂对象,专门用来生产美式咖啡
 * @Author: lzq
 */
public class AmericanCoffeeFactory implements CoffeeFactory {

    @Override
    public Coffee createCoffee() {
        return new AmericanCoffee();
    }
}

package com.study.notes.design.patterns.pattern.create.factory.factory_method.factory;

import com.study.notes.design.patterns.pattern.create.factory.factory_method.bean.LatteCoffee;
import com.study.notes.design.patterns.pattern.create.factory.factory_method.bean.Coffee;

/**
 * @version v1.0
 * @ClassName: LatteCoffeeFactory
 * @Description: 拿铁咖啡工厂,专门用来生产拿铁咖啡
 * @Author: lzq
 */
public class LatteCoffeeFactory implements CoffeeFactory {

    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }
}

package com.study.notes.design.patterns.pattern.create.factory.factory_method.store;


import com.study.notes.design.patterns.pattern.create.factory.factory_method.factory.CoffeeFactory;
import com.study.notes.design.patterns.pattern.create.factory.factory_method.bean.Coffee;

/**
 * @version v1.0
 * @ClassName: CoffeeStore
 * @Description: TODO(一句话描述该类的功能)
 * @Author: lzq
 */
public class CoffeeStore {

    private CoffeeFactory factory;

    public void setFactory(CoffeeFactory factory) {
        this.factory = factory;
    }

    //点咖啡功能
    public Coffee orderCoffee() {
        Coffee coffee = factory.createCoffee();
        //加配料
        coffee.addMilk();
        coffee.addSugar();
        return coffee;
    }
}

package com.study.notes.design.patterns.pattern.create.factory.factory_method;

import com.study.notes.design.patterns.pattern.create.factory.factory_method.factory.CoffeeFactory;
import com.study.notes.design.patterns.pattern.create.factory.factory_method.factory.LatteCoffeeFactory;
import com.study.notes.design.patterns.pattern.create.factory.factory_method.store.CoffeeStore;
import com.study.notes.design.patterns.pattern.create.factory.factory_method.bean.Coffee;

/**
 * @version v1.0
 * @ClassName: Client
 * @Description: TODO(一句话描述该类的功能)
 * @Author: lzq
 */
public class Client {
    public static void main(String[] args) {
        //创建咖啡店对象
        CoffeeStore store = new CoffeeStore();
        //创建对象
        //CoffeeFactory factory = new AmericanCoffeeFactory();
        CoffeeFactory factory = new LatteCoffeeFactory();
        store.setFactory(factory);

        //点咖啡
        Coffee coffee = store.orderCoffee();

        System.out.println(coffee.getName());
    }
}


📌 抽象工厂

  • 产品族与产品等级结构:

    • 📌 用于生产不同产品族的全部产品。
    • 📌 有多个产品等级结构,每个等级结构对应多种产品。
    • ⚠️ 注意: 支持拓展增加产品;同时也支持增加产品族。
  • 适用场合:

    • 📌 举例: 除了原有的瑞幸和星巴克咖啡,现在这两个品牌的工厂都开始生产甜品(增加产品族)。
    • 📌 无论是瑞幸还是星巴克,他们不仅生产两种固定类型的咖啡:美式咖啡拿铁咖啡,还生产各种甜品。
    • ⚠️ 注意: 由于采用抽象工厂模式,当我们需要新增其他品牌的咖啡工厂或新增其他种类的产品时,可以很方便地拓展。
      在这里插入图片描述
package com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean;

/**
 * @version v1.0
 * @ClassName: Coffee
 * @Description: 咖啡类
 * @Author: lzq
 */
public abstract class Coffee {

    public abstract String getName();

    //加糖
    public void addSugar() {
        System.out.println("加糖");
    }

    //加奶
    public void addMilk() {
        System.out.println("加奶");
    }
}

package com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean;

/**
 * @version v1.0
 * @ClassName: AmericanCoffee
 * @Description: 没事咖啡
 * @Author: lzq
 */
public class AmericanCoffee extends Coffee {

    @Override
    public String getName() {
        return "美式咖啡";
    }
}

package com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean;

/**
 * @version v1.0
 * @ClassName: LatteCoffee
 * @Description: 拿铁咖啡
 * @Author: lzq
 */
public class LatteCoffee extends Coffee {

    @Override
    public String getName() {
        return "拿铁咖啡";
    }
}

package com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean;

/**
 * @version v1.0
 * @ClassName: Dessert
 * @Description: 甜品抽象类
 * @Author: lzq
 */
public abstract class Dessert {

    public abstract void show();
}

package com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean;

/**
 * @version v1.0
 * @ClassName: MatchaMousse
 * @Description: 抹茶慕斯类
 * @Author: lzq
 */
public class MatchaMousse extends Dessert {
    @Override
    public void show() {
        System.out.println("抹茶慕斯");
    }
}

package com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean;


/**
 * @version v1.0
 * @ClassName: Trimisu
 * @Description: 提拉米苏类
 * @Author: lzq
 */
public class Trimisu extends Dessert {
    @Override
    public void show() {
        System.out.println("提拉米苏");
    }
}

package com.study.notes.design.patterns.pattern.create.factory.abstract_factory.factory;

import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.Dessert;
import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.Coffee;

/**
 * @version v1.0
 * @ClassName: DessertFactory
 * @Description: TODO(一句话描述该类的功能)
 * @Author: lzq
 */
public interface DessertFactory {

    //生产咖啡的功能
    Coffee createCoffee();

    //生产甜品的功能
    Dessert createDessert();
}

package com.study.notes.design.patterns.pattern.create.factory.abstract_factory.factory;

import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.AmericanCoffee;
import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.Coffee;
import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.Dessert;
import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.MatchaMousse;

/**
 * @version v1.0
 * @ClassName: AmericanDessertFactory
 * @Description: 美式风味的甜品工厂
 * 生产美式咖啡和抹茶慕斯
 * @Author: lzq
 */
public class AmericanDessertFactory implements DessertFactory {

    @Override
    public Coffee createCoffee() {
        return new AmericanCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new MatchaMousse();
    }
}

package com.study.notes.design.patterns.pattern.create.factory.abstract_factory.factory;

import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.Trimisu;
import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.Coffee;
import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.Dessert;
import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.LatteCoffee;

/**
 * @version v1.0
 * @ClassName: ItalyDessertFactory
 * @Description: 意大利风味甜品工厂
 * 生产拿铁咖啡和提拉米苏甜品
 * @Author: lzq
 */
public class ItalyDessertFactory implements DessertFactory {

    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new Trimisu();
    }
}

package com.study.notes.design.patterns.pattern.create.factory.abstract_factory;

import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.Dessert;
import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.bean.Coffee;
import com.study.notes.design.patterns.pattern.create.factory.abstract_factory.factory.AmericanDessertFactory;

/**
 * @version v1.0
 * @ClassName: Client
 * @Description: TODO(一句话描述该类的功能)
 * @Author: lzq
 */
public class Client {
    public static void main(String[] args) {
        //创建的是意大利风味甜品工厂对象
        //ItalyDessertFactory factory = new ItalyDessertFactory();
        AmericanDessertFactory factory = new AmericanDessertFactory();
        //获取拿铁咖啡和提拉米苏甜品
        Coffee coffee = factory.createCoffee();
        Dessert dessert = factory.createDessert();

        System.out.println(coffee.getName());
        dessert.show();
    }
}


⚡️ 经典工厂模式Collection.iterator方法

在这里插入图片描述


🟢 CollectionIterator

  • 关系:

    • 📌 Collection 接口作为抽象工厂类。
    • 📌 ArrayList (以及其他如 HashSet, LinkedList 等) 为具体的工厂类。
    • 📌 Iterator 接口作为抽象商品类。
    • 📌 ArrayList 中的 iterator 内部类为具体的商品类。
  • 实现:

    • 📌 在 ArrayList (具体工厂) 中,iterator 方法创建了 Iterator 的具体实现 (具体商品) 的对象。

🟢 DateFormat

  • 📌 DateFormat 类中的 getInstance 方法使用的是工厂模式。
    • ⚠️ 注意: 通过 DateFormat.getInstance(),我们可以得到日期/时间格式化的具体实例,而不需要关心其具体实现。

🟢 Calendar

  • 📌 Calendar 类中的 getInstance 方法使用的是工厂模式。
    • ⚠️ 注意: 通过 Calendar.getInstance(),我们可以得到日历的具体实例,而不需要关心其具体实现,可以是 GregorianCalendar 或其他日历的实现。

⚠️ 注意: Java 标准库中有许多设计模式的应用,工厂模式只是其中之一。这些模式为开发者提供了方便的 API,同时隐藏了具体实现的细节。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yueerba126

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值