在我们的日常开发中,很多地方都可以用上工厂方法模式(事实是基础开发中,大部分人从来都不会去考虑使用)。
Define an interface for creating an object, but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
类图说明:在工厂方法模式中,抽象产品类Product(或接口)负责定义产品的共性,实现对产品对抽象的定义,ConcreteProduct表示为具体的产品;Factory为抽象工厂,可以定义为抽象类或接口,具体如何创建产品类是由具体的实现工厂ConcreteFactory来完成的。
1、具有良好的封装性,代码结构清晰。调用者需要一个具体的产品对象,只要知道这个对象的类名即可,不需要知道对象创建的过程,降低了模块直接的耦合度。
2、具有优秀的扩展性,在增加产品类的情况下,只需要适当的修改具体的工厂类或扩展一个工厂类即可
3、屏蔽了产品类,产品类的实现如何变化,调用者都不关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化。因为产品类的实例化工作是由工厂类负责的,一个产品对象具体是由哪一个产品生成是有工厂决定的。
1、工厂方法模式是new一个对象的代替需要品,所以在所有需要生成对象的地方,但需要慎重的考虑是否需要增加一个工厂类进行管理,增加代码的复杂度。
2、需要灵活的、可扩张的框架时,可以考虑使用工厂方法模式。
3、在异构项目中,可以考虑使用工厂方法模式。
抽象产品类(或接口):Product.java
package com.hongke.factoryMethod;
/**
* @author chengjunyu
* @classname Product
* @description 抽象产品类,该类也可以转为接口,通过具体产品实现
* @date 2020/8/2 11:17
*/
public abstract class Product {
//产品类的公共方法
public void publicMethod() {
}
//抽象方法
public abstract void abstractMethod();
}
具体产品类,继承自抽象产品类:ConcreteMethod.java
package com.hongke.factoryMethod;
/**
* @author chengjunyu
* @classname ConcreteMethod
* @description 具体的产品类,这样的类应该是有多个,每一个都继承自产品类并重写产品类中的抽象方法
* @date 2020/8/2 11:25
*/
public class ConcreteProduct extends Product {
@Override
public void abstractMethod() {
//具体的产品类需要实现的业务逻辑
}
}
抽象工厂类,为工厂的具体实现提供扩展(也可以不要,不要的话就转为了简单工厂模式):Factory.java
package com.hongke.factoryMethod;
/**
* @author chengjunyu
* @classname Factory
* @description 抽象工厂类
* @date 2020/8/2 11:36
*/
public abstract class Factory {
public abstract T createProduct(Class t);
}
具体工厂类,抽象工厂或工厂接口的具体实现类:ConcreteFactory.java
package com.hongke.factoryMethod;
/**
* @author chengjunyu
* @classname ConcreteFacory
* @description TODO
* @date 2020/8/2 11:41
*/
public class ConcreteFacory extends Factory {
@Override
public T createProduct(Class t) {
Product product = null;
try {
//通过java反射获取传入的真实的对象
product = (Product)Class.forName(t.getName()).newInstance();
}catch (Exception e) {
System.out.println("产品创建失败");
}
return (T)product;
}
}
华为研发了多个系列手机,比如mate系列,nova系列,还有现在剥离出去的honor系列等,每个系列的手机都需要人去制造才能产生,那么案例就以制造这三个系列手机展开,代码如下:
Product:HuaweiMobile.java
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiMobile
* @Description 华为手机抽象类,定义手机的特征/行为等方法,也可以使用接口,在子类中实现方法
* @Author chengjunyu
* @Date 2022/2/2 19:18
* @Version 1.0
*/
public abstract class HuaweiMobile {
public void mobileBrand() {
System.out.println("华为品牌手机");
}
public abstract void mobileSeries();
}
ConcreteProduct1:HuaweiMate.java
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiMate
* @Description mate系列手机,继承父类并实现抽象方法
* @Author chengjunyu
* @Date 2022/2/2 19:23
* @Version 1.0
*/
public class HuaweiMate extends HuaweiMobile {
@Override
public void mobileSeries() {
System.out.println("华为mate系列");
}
}
ConcreteProduct2:HuaweiNova.java
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiNova
* @Description nova系列手机,继承父类并实现抽象方法
* @Author chengjunyu
* @Date 2022/2/2 19:21
* @Version 1.0
*/
public class HuaweiNova extends HuaweiMobile {
@Override
public void mobileSeries() {
System.out.println("华为nova系列");
}
}
ConcreteProduct3:HuaweiHonor.java
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiHonor
* @Description honor系列手机,继承父类并实现抽象方法
* @Author chengjunyu
* @Date 2022/2/2 19:24
* @Version 1.0
*/
public class HuaweiHonor extends HuaweiMobile {
@Override
public void mobileSeries() {
System.out.println("华为honor系列");
}
}
Facotry:MobileFactory.java(此处也可以使用接口)
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName AbstractHuaweiMobileFactory
* @Description 抽象工具,定义创建手机的方法
* @Author chengjunyu
* @Date 2022/2/2 19:25
* @Version 1.0
*/
public abstract class MobileFactory {
public abstract T createHuaweiMobile(Class t);
}
ConcreteFactory:HuaweiNova7Factory.java
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiMobileFactory
* @Description 继承MobileFactory,具体的生产实在在该工厂中完成
* @Author chengjunyu
* @Date 2022/2/2 19:28
* @Version 1.0
*/
public class HuaweiMobileFactory extends MobileFactory {
@Override
public T createHuaweiMobile(Class t) {
HuaweiMobile huaweiMobile = null;
try {
huaweiMobile = (T)Class.forName(t.getName()).newInstance();
}catch (Exception e) {
System.out.println("华为手机生产失败。。。");
}
return (T) huaweiMobile;
}
}
华为员工开始生产Huawei品牌手机:
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiWorker
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 19:32
* @Version 1.0
*/
public class HuaweiWorker {
public static void main(String[] args) {
// 实例化工厂,具体如何创建产品由具体实现工厂HuaweiMobileFactory完成
MobileFactory mobileFactory = new HuaweiMobileFactory();
System.out.println("制造一台华为mate系列手机");
HuaweiMobile huaweiMate = mobileFactory.createHuaweiMobile(HuaweiMate.class);
huaweiMate.mobileBrand();
huaweiMate.mobileSeries();
System.out.println("制造一台华为nova系列手机");
HuaweiMobile huaweiNova = mobileFactory.createHuaweiMobile(HuaweiNova.class);
huaweiNova.mobileBrand();
huaweiNova.mobileSeries();
System.out.println("制造一台华为honor系列手机");
HuaweiMobile huaweiHonor = (new HuaweiHonorFactory()).createHuaweiMobile();
huaweiHonor.mobileBrand();
huaweiHonor.mobileSeries();
}
}
打印结果如下:
1、缩小范围,转为简单工厂模式。该模式是工厂方法模式的弱化,也叫做静态工厂模式,不需要再创建工厂的抽象类或接口,直接创建工厂的实现,并将类中的方法修改程static方法,简单实用。缺点是工厂类的扩展不再变得比较困难,不符合开闭原则。
新建简单工厂HuaweiSimpleFactory.java。
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiSimpleFactory
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 21:57
* @Version 1.0
*/
public class HuaweiSimpleFactory {
public static T createHuaweiMobile(Class t) {
HuaweiMobile huaweiMobile = null;
try {
huaweiMobile = (T)Class.forName(t.getName()).newInstance();
}catch (Exception e) {
System.out.println("华为手机生产失败");
}
return (T) huaweiMobile;
}
}
新建工厂生产场景类
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiSimpleFactoryMain
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 22:02
* @Version 1.0
*/
public class HuaweiSimpleFactoryMain {
public static void main(String[] args) {
HuaweiMobile huaweiMate = HuaweiSimpleFactory.createHuaweiMobile(HuaweiMate.class);
huaweiMate.mobileBrand();
huaweiMate.mobileSeries();
HuaweiMobile huaweiNova = HuaweiSimpleFactory.createHuaweiMobile(HuaweiNova.class);
huaweiMate.mobileBrand();
huaweiMate.mobileSeries();
HuaweiMobile huaweiHonor = HuaweiSimpleFactory.createHuaweiMobile(HuaweiHonor.class);
huaweiMate.mobileBrand();
huaweiMate.mobileSeries();
}
}
打印结果如下,和之前通过工厂方法模式结果相同:
2、升级为多个工厂类
Huawei Mobile的工厂本来只有一条生产线在生产3个型号的产品,现在华为的手机在市场上很受欢迎,很多人要买,一条生产线忙不过来了,需要增加生产线,每个生产线做一个型号的产品,可以将原来的代码结构修改为如下:
修改华为工厂接口:HuaweiFactory.java
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiFactory
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 20:28
* @Version 1.0
*/
public interface HuaweiFactory {
public HuaweiMobile createHuaweiMobile();
}
创建一个专门生产Mate系列的工厂:HuaweiMateFactory.java
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiMateFactory
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 20:30
* @Version 1.0
*/
public class HuaweiMateFactory implements HuaweiFactory {
@Override
public HuaweiMobile createHuaweiMobile() {
return new HuaweiMate();
}
}
创建一个专门生产Nova系列的工厂:HuaweiNovaFactory.java
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiNovaFactory
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 20:29
* @Version 1.0
*/
public class HuaweiNovaFactory implements HuaweiFactory {
@Override
public HuaweiMobile createHuaweiMobile() {
return new HuaweiNova();
}
}
创建一个专门生产Honor系列的工厂:HuaweiHonorFactory.java
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiHonorFactory
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 20:32
* @Version 1.0
*/
public class HuaweiHonorFactory implements HuaweiFactory {
@Override
public HuaweiMobile createHuaweiMobile() {
return new HuaweiHonor();
}
}
华为员工生产华为手机场景类,这里仅改变honor系列的获取方法:
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName HuaweiWorker
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 19:32
* @Version 1.0
*/
public class HuaweiWorker {
public static void main(String[] args) {
// 实例化工厂,具体如何创建产品由具体实现工厂HuaweiMobileFactory完成
MobileFactory mobileFactory = new HuaweiMobileFactory();
System.out.println("制造一台华为mate系列手机");
HuaweiMobile huaweiMate = mobileFactory.createHuaweiMobile(HuaweiMate.class);
huaweiMate.mobileBrand();
huaweiMate.mobileSeries();
System.out.println("制造一台华为nova系列手机");
HuaweiMobile huaweiNova = mobileFactory.createHuaweiMobile(HuaweiNova.class);
huaweiNova.mobileBrand();
huaweiNova.mobileSeries();
System.out.println("制造一台华为honor系列手机");
HuaweiMobile huaweiHonor = (new HuaweiHonorFactory()).createHuaweiMobile();
huaweiHonor.mobileBrand();
huaweiHonor.mobileSeries();
}
}
结果打印如下,和之前使用工厂方法模式、简单工厂模式的结果一致:
3、工作方法模式替换单例模式
创建一个单例对象,私有化构造方法。
public class Singleton {
private Singleton() {
}
public void doSomething() {
System.out.println("单例对象创建完成。。。");
}
}
public class SingletonFactory {
private static Singleton singleton;
static {
try {
Class c = Class.forName(Singleton.class.getName());
Constructor constructor = c.getDeclaredConstructor();
constructor.setAccessible(true);
singleton = (Singleton) constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Singleton getSingleton() {
return singleton;
}
}
public class SingletonMain {
public static void main(String[] args) {
Singleton singleton = SingletonFactory.getSingleton();
singleton.doSomething();
Singleton singleton1 = SingletonFactory.getSingleton();
System.out.println(singleton == singleton1);
}
}
4、延迟初始化
延迟初始化是指一个对象消费完毕后,并不立刻释放,工厂类保持其初始状态,等待对象再次被使用。
工厂类负责产品对象创建工作,并通过map变量产生一个缓存,将需要再次被使用的对象保存到map中。
创建延迟初始化工厂。
package com.springcloud.alibaba.factoryMethod;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName LazyInitializationFactory
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 21:22
* @Version 1.0
*/
public class LazyInitializationFactory {
public static final Map mobileMap = new HashMap<>();
public static synchronized HuaweiMobile createMobile(String mobileType) throws Exception {
HuaweiMobile huaweiMobile = null;
if(mobileMap.containsKey(mobileType)) {
huaweiMobile = mobileMap.get(mobileType);
}else {
if(mobileType.equals("huaweiMate")) {
huaweiMobile = new HuaweiMate();
}else if(mobileType.equals("huaweiNova")) {
huaweiMobile = new HuaweiNova();
}else if(mobileType.equals("huaweiHonor")) {
huaweiMobile = new HuaweiHonor();
}
mobileMap.put(mobileType, huaweiMobile);
}
return huaweiMobile;
}
}
创建延迟加载对象场景:
package com.springcloud.alibaba.factoryMethod;
/**
* @ClassName LazyInitializationFactoryMain
* @Description TODO
* @Author chengjunyu
* @Date 2022/2/2 21:40
* @Version 1.0
*/
public class LazyInitializationFactoryMain {
public static void main(String[] args) throws Exception {
HuaweiMobile huaweiMate = LazyInitializationFactory.createMobile("huaweiMate");
huaweiMate.mobileBrand();
huaweiMate.mobileSeries();
HuaweiMobile huaweiNova = LazyInitializationFactory.createMobile("huaweiNova");
huaweiNova.mobileBrand();
huaweiNova.mobileSeries();
HuaweiMobile huaweiHonor = LazyInitializationFactory.createMobile("huaweiHonor");
huaweiHonor.mobileBrand();
huaweiHonor.mobileSeries();
}
}
执行结果: