定义一个用于创建产品的接口,由子类决定生产什么产品。
分类- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
简单工厂模式是有一个工厂对象决定创建出哪一种产品类的实例。即定义了一个创建对象的类,由这个类来封装实例化对象的行为。
简单工厂有两种模式:
- 普通简单工厂模式;
- 静态简单工厂模式;
- 抽象产品:定义了产品的规范,描述了产品的主要特征和功能;
- 具体产品:实现或者继承抽象产品的子类;
- 具体工厂:提供了创建产品的方法,调用者通过该方法创建产品;
● 简单工厂模式,通过接收的参数不同来返回不同的对象实例;
● 对于增加新产品(新功能)无能为力!不修改代码的话,是无法扩展的。不满足开闭原则。
抽象类Pizza
package top.simba1949.factory.simple.pizza;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* @author anthony
* @datetime 2020/5/9 11:45
*/
@Slf4j
@Data
public abstract class Pizza {
protected String name;
/**
* 准备原材料,每种 Pizza 原材料不一致
*/
public abstract void prepare();
/**
* Pizza 烘烤
*/
public void bake() {
log.info("{} : baking", name);
}
/**
* Pizza 切割
*/
public void cut() {
log.info("{} : cutting", name);
}
/**
* Pizza 打包
*/
public void box() {
log.info("{} : boxing", name);
}
}
抽象类Pizza的实现
package top.simba1949.factory.simple.pizza;
import lombok.extern.slf4j.Slf4j;
/**
* @author anthony
* @datetime 2020/5/9 11:51
*/
@Slf4j
public class CheesePizza extends Pizza {
@Override
public void prepare() {
log.info("芝士Pizza原材料准备中。。。");
}
}
package top.simba1949.factory.simple.pizza;
import lombok.extern.slf4j.Slf4j;
/**
* @author anthony
* @datetime 2020/5/9 11:52
*/
@Slf4j
public class GreekPizza extends Pizza {
@Override
public void prepare() {
log.info("希腊风味Pizza原材料准备中。。。");
}
}
简单工厂(静态)
package top.simba1949.factory.simple.staticFacotry;
import top.simba1949.factory.simple.pizza.CheesePizza;
import top.simba1949.factory.simple.pizza.GreekPizza;
import top.simba1949.factory.simple.pizza.Pizza;
/**
* @author anthony
* @datetime 2020/5/9 12:51
*/
public class SimpleFactoryByStatic {
public static Pizza orderPizza(String type) {
Pizza pizza = null;
if ("cheese".equalsIgnoreCase(type)) {
pizza = new CheesePizza();
pizza.setName("cheese");
} else if ("greek".equalsIgnoreCase(type)) {
pizza = new GreekPizza();
pizza.setName("greek");
}
if (null != pizza){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
return pizza;
}
}
简单工厂模式(普通)
package top.simba1949.factory.simple.commonFactory;
import top.simba1949.factory.simple.pizza.CheesePizza;
import top.simba1949.factory.simple.pizza.GreekPizza;
import top.simba1949.factory.simple.pizza.Pizza;
/**
* @author anthony
* @datetime 2023/7/15 13:19
*/
public class SimpleFactoryByCommon {
public Pizza orderPizza(String type) {
Pizza pizza = null;
if ("cheese".equalsIgnoreCase(type)) {
pizza = new CheesePizza();
pizza.setName("cheese");
} else if ("greek".equalsIgnoreCase(type)) {
pizza = new GreekPizza();
pizza.setName("greek");
}
if (null != pizza){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
return pizza;
}
}
测试类
package top.simba1949.factory.simple;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.simple.commonFactory.SimpleFactoryByCommon;
import top.simba1949.factory.simple.pizza.Pizza;
import top.simba1949.factory.simple.staticFacotry.SimpleFactoryByStatic;
/**
* @author anthony
* @datetime 2020/5/9 13:50
*/
@Slf4j
public class SimpleFactoryApplication {
public static void main(String[] args) {
String pizzaType = "cheese";
// 简单工厂(静态)模式
// simpleFactoryByStatic(pizzaType);
// 简单工厂(普通)模式
simpleFactoryByCommon(pizzaType);
}
public static void simpleFactoryByStatic(String pizzaType){
// 用户订购 Pizza
Pizza pizza = SimpleFactoryByStatic.orderPizza(pizzaType);
// 得到 Pizza
log.info("简单工厂(静态):订购的披萨是{}", pizza);
}
public static void simpleFactoryByCommon(String pizzaType){
SimpleFactoryByCommon simpleFactoryByCommon = new SimpleFactoryByCommon();
// 用户订购 Pizza
Pizza pizza = simpleFactoryByCommon.orderPizza(pizzaType);
// 得到 Pizza
log.info("简单工厂(普通):订购的披萨是{}", pizza);
}
}
工厂方法模式
工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。
工程方法模式将对象的实例化推迟到子类实例化。
- 抽象工厂:提供了创建产品的接口,调用者通过它访问到具体工厂的工厂方法来创建产品;
- 具体工厂:主要是实现抽象工厂的抽象方法,完成具体产品的创建;
- 抽象产品:定义了产品的规范,描述了产品的主要特征和功能;
- 具体产品:实现类抽象产品所定义的接口,有具体工厂来创建,它同具体工厂一一对应;
优点
- 用户只需要知道具体工厂的名称就可以得到所要的产品,无需知道产品的具体创建过程;
- 在系统增加新产品时只需要添加具体产品类和对应的具体工厂类,无需对原工厂进行任何修改,满足开闭原则。
缺点
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类增加了系统的复杂化度。产生类爆炸;
UML 类图描述
咖啡类
package top.simba1949.factory.method.coffee;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* @author anthony
* @datetime 2023/7/15 13:46
*/
@Slf4j
@Data
public abstract class Coffee {
private String name;
public void addMilk(){
log.info("{} 添加了牛奶", name);
}
public void addSugar(){
log.info("{} 添加了糖", name);
}
}
package top.simba1949.factory.method.coffee;
/**
* @author anthony
* @datetime 2023/7/15 13:51
*/
public class AmericanoCoffee extends Coffee {
}
package top.simba1949.factory.method.coffee;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* @author anthony
* @datetime 2023/7/15 13:53
*/
@Slf4j
@Data
public class LatteCoffee extends Coffee {
}
工厂类
package top.simba1949.factory.method.factory;
import top.simba1949.factory.method.coffee.Coffee;
/**
* @author anthony
* @datetime 2023/7/15 13:48
*/
public abstract class CoffeeFactory {
public abstract Coffee createCoffee();
}
package top.simba1949.factory.method.factory;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.method.coffee.AmericanoCoffee;
import top.simba1949.factory.method.coffee.Coffee;
/**
* @author anthony
* @datetime 2023/7/15 13:49
*/
@Slf4j
public class AmericanoCoffeeFactory extends CoffeeFactory {
@Override
public Coffee createCoffee() {
Coffee coffee = new AmericanoCoffee();
coffee.setName("美式咖啡");
return coffee;
}
}
package top.simba1949.factory.method.factory;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.method.coffee.Coffee;
import top.simba1949.factory.method.coffee.LatteCoffee;
/**
* @author anthony
* @datetime 2023/7/15 13:49
*/
@Slf4j
public class LatteCoffeeFactory extends CoffeeFactory {
@Override
public Coffee createCoffee() {
Coffee coffee = new LatteCoffee();
coffee.setName("拿铁咖啡");
return coffee;
}
}
咖啡店
package top.simba1949.factory.method;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.method.coffee.Coffee;
import top.simba1949.factory.method.factory.CoffeeFactory;
/**
* @author anthony
* @datetime 2023/7/15 13:52
*/
@Slf4j
@Data
public class CoffeeStore {
public CoffeeFactory coffeeFactory;
public Coffee orderCoffee(){
// 这里创建对应的对象
Coffee coffee = coffeeFactory.createCoffee();
coffee.addMilk();
coffee.addSugar();
return coffee;
}
}
测试类
package top.simba1949.factory.method;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.method.coffee.Coffee;
import top.simba1949.factory.method.factory.AmericanoCoffeeFactory;
import top.simba1949.factory.method.factory.CoffeeFactory;
/**
* @author anthony
* @datetime 2020/5/9 14:30
*/
@Slf4j
public class MethodFactoryApplication {
public static void main(String[] args) {
// 创建咖啡店对象
CoffeeStore coffeeStore = new CoffeeStore();
// 创建工厂对象
CoffeeFactory coffeeFactory = new AmericanoCoffeeFactory();
coffeeStore.setCoffeeFactory(coffeeFactory);
// 订购咖啡
Coffee coffee = coffeeStore.orderCoffee();
log.info("订购的咖啡是:{}", coffee);
}
}
抽象工厂模式
是一种为访问类提供一个创建一组相关或者相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同组的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂可生产多个等级的产品。
- 抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品;
- 具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建;
- 抽象产品:定义了产品的规范,描述了产品的主要特征和功能,抽象工厂模式有多个抽象产品;
- 具体产品:实现了抽象产品角色所定义的接口,由具体工厂创建,它同具体工厂是多对一的关系;
优点
当一个产品族中的多个对象被设计成一起工作时,他能保证客户端始终只使用同一个产品族中的对象;
缺点
当产品族中需要新增一个新的产品,所有的工厂类都需要进行修改;
使用场景- 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
- 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
- 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。
如:输入法换皮肤,一整套一起换。生成不同操作系统的程序。
抽象工厂模式的实现UML
甜点
package top.simba1949.factory.abs.dessert;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* @author anthony
* @datetime 2023/7/15 14:25
*/
@Slf4j
@Data
public abstract class Dessert {
private String name;
public void show() {
log.info("正在展示的甜点是{}", name);
}
}
package top.simba1949.factory.abs.dessert;
/**
* 抹茶慕斯
*
* @author anthony
* @datetime 2023/7/15 14:28
*/
public class MatchaMousseDessert extends Dessert{
}
package top.simba1949.factory.abs.dessert;
/**
* 提拉米苏
*
* @author anthony
* @datetime 2023/7/15 14:26
*/
public class TiramisuDessert extends Dessert {
}
咖啡
package top.simba1949.factory.abs.coffee;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* @author anthony
* @datetime 2023/7/15 14:26
*/
@Slf4j
@Data
public abstract class Coffee {
private String name;
public void addMilk(){
log.info("{} 添加了牛奶", name);
}
public void addSugar(){
log.info("{} 添加了糖", name);
}
}
package top.simba1949.factory.abs.factory;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.abs.coffee.AmericanoCoffee;
import top.simba1949.factory.abs.coffee.Coffee;
import top.simba1949.factory.abs.dessert.Dessert;
import top.simba1949.factory.abs.dessert.MatchaMousseDessert;
/**
* @author anthony
* @datetime 2023/7/15 14:32
*/
@Slf4j
public class AmericanFactory extends AbsFactory {
@Override
public Coffee createCoffee() {
Coffee coffee = new AmericanoCoffee();
coffee.setName("美式咖啡");
coffee.addSugar();
return coffee;
}
@Override
public Dessert createDessert() {
Dessert dessert = new MatchaMousseDessert();
dessert.setName("抹茶慕斯");
return dessert;
}
}
package top.simba1949.factory.abs.factory;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.abs.coffee.Coffee;
import top.simba1949.factory.abs.coffee.LatteCoffee;
import top.simba1949.factory.abs.dessert.Dessert;
import top.simba1949.factory.abs.dessert.TiramisuDessert;
/**
* @author anthony
* @datetime 2023/7/15 14:32
*/
@Slf4j
public class ItalyFactory extends AbsFactory {
@Override
public Coffee createCoffee() {
Coffee coffee = new LatteCoffee();
coffee.setName("拿铁咖啡");
coffee.addMilk();
return coffee;
}
@Override
public Dessert createDessert() {
Dessert dessert = new TiramisuDessert();
dessert.setName("提拉米苏");
return dessert;
}
}
工厂
package top.simba1949.factory.abs.factory;
import top.simba1949.factory.abs.coffee.Coffee;
import top.simba1949.factory.abs.dessert.Dessert;
/**
* @author anthony
* @datetime 2023/7/15 14:31
*/
public abstract class AbsFactory {
public abstract Coffee createCoffee();
public abstract Dessert createDessert();
}
package top.simba1949.factory.abs.factory;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.abs.coffee.AmericanoCoffee;
import top.simba1949.factory.abs.coffee.Coffee;
import top.simba1949.factory.abs.dessert.Dessert;
import top.simba1949.factory.abs.dessert.MatchaMousseDessert;
/**
* @author anthony
* @datetime 2023/7/15 14:32
*/
@Slf4j
public class AmericanFactory extends AbsFactory {
@Override
public Coffee createCoffee() {
Coffee coffee = new AmericanoCoffee();
coffee.setName("美式咖啡");
coffee.addSugar();
return coffee;
}
@Override
public Dessert createDessert() {
Dessert dessert = new MatchaMousseDessert();
dessert.setName("抹茶慕斯");
return dessert;
}
}
package top.simba1949.factory.abs.factory;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.abs.coffee.Coffee;
import top.simba1949.factory.abs.coffee.LatteCoffee;
import top.simba1949.factory.abs.dessert.Dessert;
import top.simba1949.factory.abs.dessert.TiramisuDessert;
/**
* @author anthony
* @datetime 2023/7/15 14:32
*/
@Slf4j
public class ItalyFactory extends AbsFactory {
@Override
public Coffee createCoffee() {
Coffee coffee = new LatteCoffee();
coffee.setName("拿铁咖啡");
coffee.addMilk();
return coffee;
}
@Override
public Dessert createDessert() {
Dessert dessert = new TiramisuDessert();
dessert.setName("提拉米苏");
return dessert;
}
}
测试
package top.simba1949.factory.abs;
import lombok.extern.slf4j.Slf4j;
import top.simba1949.factory.abs.coffee.Coffee;
import top.simba1949.factory.abs.dessert.Dessert;
import top.simba1949.factory.abs.factory.ItalyFactory;
/**
* @author anthony
* @datetime 2023/7/15 14:37
*/
@Slf4j
public class AbsFactoryApplication {
public static void main(String[] args) {
ItalyFactory italyFactory = new ItalyFactory();
Coffee coffee = italyFactory.createCoffee();
log.info("订购的咖啡是:{}", coffee);
Dessert dessert = italyFactory.createDessert();
log.info("订购的甜品是:{}", dessert);
}
}
JDK 源码中的工厂模式
Calendar instance = Calendar.getInstance();
public static Calendar getInstance()
{
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
private static Calendar createCalendar(TimeZone zone, Locale aLocale)
{
CalendarProvider provider = LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
// 根据不同的入参,返回不同的Calendar子类
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
if (cal == null) {
// If no known calendar type is explicitly specified,
// perform the traditional way to create a Calendar:
// create a BuddhistCalendar for th_TH locale,
// a JapaneseImperialCalendar for ja_JP_JP locale, or
// a GregorianCalendar for any other locales.
// NOTE: The language, country and variant strings are interned.
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}