⚡️ 工厂模式
-
🛠️ 简单工厂模式:
- 📌 描述: 建立一个实例化对象的类,该类中可以对多个对象进行实例化。
- ⚠️ 注意: 它是一个具体的类,不是接口或抽象类。所有的对象创建请求都通过这个类的静态方法来完成。
-
🛠️ 工厂方法模式:
- 📌 描述: 定义了一个创建对象的抽象方法,由子类决定要实例化的类。
- ⚠️ 注意: 在有新的类型的对象需要实例化时,只需增加相应的子类即可,无需修改已有的代码。
-
🛠️ 抽象工厂模式:
- 📌 描述: 定义了一个接口用于创建对象族,但无需明确指定具体类。
- 📌 优点: 提供给客户端接口,避免了用户直接操作子类工厂。
- ⚠️ 注意: 抽象工厂也将对象的实例化交给了具体的子类工厂,从而支持拓展。
⚠️ 注意: 工厂模式是面向对象编程中的一种设计模式,用于处理对象创建的问题,特别是当直接创建对象(使用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
方法
🟢 Collection
和 Iterator
-
关系:
- 📌
Collection
接口作为抽象工厂类。 - 📌
ArrayList
(以及其他如HashSet
,LinkedList
等) 为具体的工厂类。 - 📌
Iterator
接口作为抽象商品类。 - 📌
ArrayList
中的iterator
内部类为具体的商品类。
- 📌
-
实现:
- 📌 在
ArrayList
(具体工厂) 中,iterator
方法创建了Iterator
的具体实现 (具体商品) 的对象。
- 📌 在
🟢 DateFormat
- 📌
DateFormat
类中的getInstance
方法使用的是工厂模式。- ⚠️ 注意: 通过
DateFormat.getInstance()
,我们可以得到日期/时间格式化的具体实例,而不需要关心其具体实现。
- ⚠️ 注意: 通过
🟢 Calendar
- 📌
Calendar
类中的getInstance
方法使用的是工厂模式。- ⚠️ 注意: 通过
Calendar.getInstance()
,我们可以得到日历的具体实例,而不需要关心其具体实现,可以是GregorianCalendar
或其他日历的实现。
- ⚠️ 注意: 通过
⚠️ 注意: Java 标准库中有许多设计模式的应用,工厂模式只是其中之一。这些模式为开发者提供了方便的 API,同时隐藏了具体实现的细节。