设计模式——工厂方法模式(Factory Method)

工厂方法模式:Factory Method

在我们的日常开发中,很多地方都可以用上工厂方法模式(事实是基础开发中,大部分人从来都不会去考虑使用)。

工厂方法模式英文定义:

Define an interface for creating an object, but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.

工厂方法模式中文定义:

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

工厂方法模式通用类图:

设计模式——工厂方法模式(Factory Method)_第1张图片

类图说明:在工厂方法模式中,抽象产品类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();
    }
}

打印结果如下:

设计模式——工厂方法模式(Factory Method)_第2张图片

工厂方法模式扩展:

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();
    }
}

打印结果如下,和之前通过工厂方法模式结果相同:

设计模式——工厂方法模式(Factory Method)_第3张图片

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();
    }
}

结果打印如下,和之前使用工厂方法模式、简单工厂模式的结果一致:

设计模式——工厂方法模式(Factory Method)_第4张图片

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);
    }
}

设计模式——工厂方法模式(Factory Method)_第5张图片

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();
    }
}

执行结果:

设计模式——工厂方法模式(Factory Method)_第6张图片

你可能感兴趣的:(#,Java设计模式,工厂方法模式,设计模式,工厂方法,简单工厂模式,Factory,Method)