文章目录
- 工厂模式简介
- 简单工厂(Simple Factory)
- 结构
- 具体实现
- 优缺点
- 工厂方法(Factory Method)
- 结构
- 具体实现
- 优缺点
- 抽象工厂(Abstract Factory)
- 结构
- 具体实现
- 优缺点
工厂模式简介
工厂模式是一种创建型模式,主要有三种:简单工厂(Simple Factory)、工厂方法(Factory Method)、抽象工厂(Abstract Factory)。
整个博客例子:设计一个咖啡点餐系统:设计一个咖啡类(Coffee),并定义两个子类,美式咖啡(AmericanCoffee)和拿铁咖啡(LatteCoffee),在设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。
简单工厂(Simple Factory)
结构
- 抽象产品:例如Abstract Class Coffee
- 具体产品:例如American Coffee
- 具体工厂: CoffeeSimpleFactory
具体实现
根据定义,为Coffee添加一个Coffee简单工厂类CoffeeSimpleFactory用于Coffee的生产,在CoffeeStore中先创建CoffeeSimpleFactory对象,然后根据该对象进行咖啡创建。
- UML类图
- 咖啡抽象类
package com.xxliao.pattern.creational.factory.simple_factory.demo;
/**
* @author xxliao
* @description: 咖啡类
* @date 2024/5/23 22:02
*/
public abstract class Coffee {
private String name;
public abstract String getName();
}
- 美式咖啡类(继承Coffee类)
package com.xxliao.pattern.creational.factory.simple_factory.demo;
/**
* @author xxliao
* @description: 美式咖啡
* @date 2024/5/23 22:04
*/
public class AmericanCoffee extends Coffee {
private String name = "AmericanCoffee";
@Override
public String getName() {
return name;
}
}
- 拿铁咖啡类(继承Coffee类)
package com.xxliao.pattern.creational.factory.simple_factory.demo;
/**
* @author xxliao
* @description: 拿铁咖啡
* @date 2024/5/23 22:05
*/
public class LatteCoffee extends Coffee{
private String name = "LatteCoffee";
@Override
public String getName() {
return name;
}
}
- 咖啡工厂类
package com.xxliao.pattern.creational.factory.simple_factory.demo;
/**
* @author xxliao
* @description: 咖啡简单工厂类
* @date 2024/5/23 22:07
*/
public class CoffeeSimpleFactory {
/**
* @description 生产咖啡
* @author xxliao
* @date 2024/5/23 22:07
*/
public Coffee createCoffee(String type){
Coffee coffee = null;
switch (type) {
case "american":
coffee = new AmericanCoffee();
break;
case "lattee":
coffee = new LatteCoffee();
break;
default:
break;
}
return coffee;
}
}
- 咖啡店类
package com.xxliao.pattern.creational.factory.simple_factory.demo;
/**
* @author xxliao
* @description: 咖啡店类
* @date 2024/5/23 22:10
*/
public class CoffeeStore {
/**
* @description 咖啡点餐
* @author xxliao
* @date 2024/5/23 22:12
*/
public Coffee orderCoffee(String type) {
// 创建简单工厂对象
CoffeeSimpleFactory coffeeSimpleFactory = new CoffeeSimpleFactory();
return coffeeSimpleFactory.createCoffee(type);
}
}
- 测试类
package com.xxliao.pattern.creational.factory.simple_factory;
import com.xxliao.pattern.creational.factory.simple_factory.demo.Coffee;
import com.xxliao.pattern.creational.factory.simple_factory.demo.CoffeeStore;
/**
* @author xxliao
* @description: 工厂设计模式-简单工厂模式-测试客户端
* @date 2024/5/23 22:00
*/
public class SimpleFactoryClient {
public static void main(String[] args) {
CoffeeStore coffeeStore = new CoffeeStore();
Coffee coffee = coffeeStore.orderCoffee("american");
System.out.println(coffee.getName());
}
}
优缺点
- 优点:封装了创建对象的过程,可以根据参数等直接获取对象,将对象的创建和业务逻辑层分开,易于扩展。
- 缺点:当Coffee种类增加时候CoffeeSimpleFactory的createCoffee方法需要修改,违背了开闭原则(对扩展开放,对修改关闭)
工厂方法(Factory Method)
根据简单工厂的工厂类方法扩展时需要修改代码的缺点,可以使用工厂方法模式解决。定义一个抽象工厂,为每个对象创建一个具体产品类工厂,对象的创建在工厂子类中进行。
结构
- 1.抽象工厂(abstract factory): 提供创建产品的接口,调用者通过它访问具体工厂的工厂方法类创建产品。
- 2.具体工厂(Concrete factory): 实现抽象工厂的具体类,完成具体产品的创建。
- 3.抽象产品: 例如:Coffee。
- 4.具体产品:例如:AmericanCoffee。
具体实现
- UML图
- 咖啡类(抽象产品类)
package com.xxliao.pattern.creational.factory.factory_method.demo;
/**
* @author xxliao
* @description: 咖啡类
* @date 2024/5/23 22:02
*/
public abstract class Coffee {
private String name;
public abstract String getName();
}
- 美式咖啡类(具体产品类)
package com.xxliao.pattern.creational.factory.factory_method.demo;
/**
* @author xxliao
* @description: 美式咖啡
* @date 2024/5/23 22:04
*/
public class AmericanCoffee extends Coffee {
private String name = "AmericanCoffee";
@Override
public String getName() {
return name;
}
}
- 拿铁咖啡(具体产品类)
package com.xxliao.pattern.creational.factory.factory_method.demo;
/**
* @author xxliao
* @description: 拿铁咖啡
* @date 2024/5/23 22:05
*/
public class LatteCoffee extends Coffee {
private String name = "LatteCoffee";
@Override
public String getName() {
return name;
}
}
- 咖啡抽象工厂类
package com.xxliao.pattern.creational.factory.factory_method.demo;
/**
* @author xxliao
* @description: 咖啡的抽象工厂类
* @date 2024/5/23 22:29
*/
public interface CoffeeFactory {
public Coffee createCoffee();
}
- 美式咖啡工厂类(具体工厂类)
package com.xxliao.pattern.creational.factory.factory_method.demo;
/**
* @author xxliao
* @description: 美式咖啡工厂类
* @date 2024/5/23 22:07
*/
public class AmericanCoffeeFactory implements CoffeeFactory{
/**
* @description 生产咖啡
* @author xxliao
* @date 2024/5/23 22:07
*/
public Coffee createCoffee(){
return new AmericanCoffee();
}
}
- 拿铁工厂类(具体工厂类)
package com.xxliao.pattern.creational.factory.factory_method.demo;
/**
* @author xxliao
* @description: 拿铁咖啡工厂类
* @date 2024/5/23 22:07
*/
public class LatteCoffeeFactory implements CoffeeFactory{
/**
* @description 生产咖啡
* @author xxliao
* @date 2024/5/23 22:07
*/
public Coffee createCoffee(){
return new LatteCoffee();
}
}
- 咖啡店类
package com.xxliao.pattern.creational.factory.factory_method.demo;
/**
* @author xxliao
* @description: 咖啡店类
* @date 2024/5/23 22:10
*/
public class CoffeeStore {
private CoffeeFactory coffeeFactory;
public CoffeeStore(CoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
/**
* @description 咖啡点餐
* @author xxliao
* @date 2024/5/23 22:12
*/
public Coffee orderCoffee() {
return coffeeFactory.createCoffee();
}
}
- 测试客户端
package com.xxliao.pattern.creational.factory.factory_method;
import com.xxliao.pattern.creational.factory.factory_method.demo.AmericanCoffeeFactory;
import com.xxliao.pattern.creational.factory.factory_method.demo.Coffee;
import com.xxliao.pattern.creational.factory.factory_method.demo.CoffeeStore;
/**
* @author xxliao
* @description: 工厂设计模式-工厂方法 - 测试客户端
* @date 2024/5/23 22:19
*/
public class FactoryMethod {
public static void main(String[] args) {
CoffeeStore coffeeStore = new CoffeeStore(new AmericanCoffeeFactory());
Coffee coffee = coffeeStore.orderCoffee();
System.out.println(coffee.getName());
}
}
优缺点
- 优点:封装了创建对象的具体过程,将对象创建和业务逻辑层进行分离,用户只需要知道具体的工厂就可以创建对应的对象,新增产品时,只需要添加对应产品类和具体工厂子类就行,无需其它代码进行修改。
- 缺点:没新增一个产品,就需要增加一个产品类以及对应的工厂类,增加了系统复杂度。
抽象工厂(Abstract Factory)
抽象工厂模式是 工厂方法的升级版,工厂方法是一个产品就有一个具体的工厂类,抽象工厂是顶级抽象工厂可以生产多种产品,然后子类工厂实现类可以生产
产品一类。
例如:定义工厂定义可以生产coffee和dessert,子类AmericanDessertFacTory可以生产AmericanCoffee和AmericanDessert。
结构
- 1.抽象工厂(abstract factory): 提供创建产品的接口,包含多个产品的拆创建方法,可以创建多个不同维度的产品。
- 2.具体工厂(Concrete factory): 实现抽象工厂的具体类,完成具体一系列产品的创建。
- 3.抽象产品: 例如:Coffee。
- 4.具体产品:例如:AmericanCoffee.
具体实现
-
UML图
-
咖啡类(抽象产品类)
package com.xxliao.pattern.creational.factory.abstract_factory.demo;
/**
* @author xxliao
* @description: 咖啡类
* @date 2024/5/23 22:02
*/
public abstract class Coffee {
private String name;
public abstract String getName();
}
- 中国咖啡类(具体产品类)
package com.xxliao.pattern.creational.factory.abstract_factory.demo;
/**
* @author xxliao
* @description: 国产中式咖啡
* @date 2024/5/23 22:05
*/
public class ChineseCoffee extends Coffee {
private String name = "ChineseCoffee";
@Override
public String getName() {
return name;
}
}
-美式咖啡类(具体产品类)
package com.xxliao.pattern.creational.factory.abstract_factory.demo;
/**
* @author xxliao
* @description: 美式咖啡
* @date 2024/5/23 22:04
*/
public class AmericanCoffee extends Coffee {
private String name = "AmericanCoffee";
@Override
public String getName() {
return name;
}
}
- 甜品类(抽象产品类)
package com.xxliao.pattern.creational.factory.abstract_factory.demo;
/**
* @author xxliao
* @description: 甜品抽象类
* @date 2024/5/23 23:07
*/
public abstract class Dessert {
private String name;
public abstract String getName();
}
- 中式甜品类(具体产品类)
package com.xxliao.pattern.creational.factory.abstract_factory.demo;
/**
* @author xxliao
* @description: 中式甜品
* @date 2024/5/23 23:10
*/
public class ChineseDessert extends Dessert{
private String name = "ChineseDessert";
public String getName() {
return name;
}
}
- 美式甜品类(具体产品类)
package com.xxliao.pattern.creational.factory.abstract_factory.demo;
/**
* @author xxliao
* @description: 美式甜品
* @date 2024/5/23 23:10
*/
public class AmericanDessert extends Dessert{
private String name = "AmericanDessert";
public String getName() {
return name;
}
}
- 烘培饮品工厂(抽象工厂类)
package com.xxliao.pattern.creational.factory.abstract_factory.demo;
/**
* @author xxliao
* @description: 烘培饮品工厂
* @date 2024/5/23 22:29
*/
public interface DessertFactory {
// 生产咖啡
Coffee createCoffee();
// 生产甜品
Dessert createDessert();
}
- 中国烘培饮品工厂(具体工厂类)
package com.xxliao.pattern.creational.factory.abstract_factory.demo;
/**
* @author xxliao
* @description: 中国烘培饮品工厂
* @date 2024/5/23 22:07
*/
public class ChineseDessertFactory implements DessertFactory {
/**
* @description 生产咖啡
* @author xxliao
* @date 2024/5/23 22:07
*/
public Coffee createCoffee(){
return new ChineseCoffee();
}
@Override
public Dessert createDessert() {
return new ChineseDessert();
}
}
- 美国烘培饮品工厂(具体工厂类)
package com.xxliao.pattern.creational.factory.abstract_factory.demo;
/**
* @author xxliao
* @description: 美国烘培饮品工厂
* @date 2024/5/23 22:07
*/
public class AmericanDessertFactory implements DessertFactory {
/**
* @description 生产咖啡
* @author xxliao
* @date 2024/5/23 22:07
*/
public Coffee createCoffee(){
return new AmericanCoffee();
}
@Override
public Dessert createDessert() {
return new AmericanDessert();
}
}
- 测试客户端
package com.xxliao.pattern.creational.factory.abstract_factory;
import com.xxliao.pattern.creational.factory.abstract_factory.demo.AmericanDessertFactory;
import com.xxliao.pattern.creational.factory.abstract_factory.demo.ChineseDessertFactory;
import com.xxliao.pattern.creational.factory.abstract_factory.demo.Coffee;
import com.xxliao.pattern.creational.factory.abstract_factory.demo.Dessert;
/**
* @author xxliao
* @description: 设计模式-工厂模式-抽象工厂模式 - 测试客户端
* @date 2024/5/23 22:59
*/
public class AbstractFactory {
public static void main(String[] args) {
// 拿到工厂类
AmericanDessertFactory americanDessertFactory = new AmericanDessertFactory();
// 生产一系列产品
Coffee americanCoffee = americanDessertFactory.createCoffee();
Dessert americanDessert = americanDessertFactory.createDessert();
System.out.println(americanDessert.getName());
System.out.println(americanCoffee.getName());
System.out.println("==========================================");
// 拿到工厂类
ChineseDessertFactory chineseDessertFactory = new ChineseDessertFactory();
// 生产一系列产品
Coffee chineseCoffee = chineseDessertFactory.createCoffee();
Dessert chineseDessert = chineseDessertFactory.createDessert();
System.out.println(chineseCoffee.getName());
System.out.println(chineseDessert.getName());
}
}
优缺点
- 优点:当一个产品族中多个对象被设计一起生产时,抽象工厂模式可以保证客户端始终只使用同一个产品族中的对象。
- 缺点:产品族中新增一个产品时候,所有的工厂类都需要修改。