工厂方法模式

工厂方法模式: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.

工厂方法模式中文定义:

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

工厂方法模式通用类图:

类图说明:在工厂方法模式中,抽象产品类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 extends Product> T createProduct(Class<T> 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 extends Product> T createProduct(Class<T> 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 extends HuaweiMobile> T createHuaweiMobile(Class<T> 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 extends HuaweiMobile> T createHuaweiMobile(Class<T> 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 extends HuaweiMobile> T createHuaweiMobile(Class<T> 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<String, HuaweiMobile> 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();
    }
}

执行结果:

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
工厂方法模式是一种常见的创建型设计模式,它定义了一个用于创建对象的接口,但是由子类决定要实例化的类是哪一个。在工厂方法模式中,创建对象的过程被分离出来,使得这个过程可以被子类定制化,从而提高了代码的可扩展性和可维护性。 工厂方法模式的核心思想是将对象的创建和使用分离开来,客户端只需要知道所需对象的类型,而无需关心对象的创建过程。具体来说,工厂方法模式包含以下几个角色: 1. 抽象工厂(Abstract Factory):定义了工厂方法的接口,用于创建产品对象。 2. 具体工厂(Concrete Factory):实现抽象工厂接口,根据具体需求创建具体产品对象。 3. 抽象产品(Abstract Product):定义了产品的接口,用于描述产品的属性和行为。 4. 具体产品(Concrete Product):实现抽象产品接口,提供具体的实现。 使用工厂方法模式可以将客户端代码和具体产品的实现代码分离开来,使得代码更加灵活和可扩展。工厂方法模式在实际应用中也有很多场景,例如: 1. 当一个类不知道它所必须创建的对象的类的时候。 2. 当一个类希望由它的子类来指定所创建的对象的时候。 3. 当类将创建对象的职责委托给多个帮助子类中的某个特定子类,并且希望能够在运行时切换这些子类中的哪一个时。 总之,工厂方法模式是一种非常实用的设计模式,可以提高代码的可维护性和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值