【设计模式】23种设计模式之工厂模式(简单工厂、工厂方法),附真实代码场景应用

什么是工厂模式?

所谓工厂模式,简单的来说,就是自己不再主动创建对象,而是让工厂来帮我们创建对象。

真实场景

统计图表需求:客户需要根据用户的性别、年龄段、居住地信息做一个可切换的统计数据。
在这里插入图片描述

如何使用?

  1. 简单实现,拿到这个需求,是不是so easy?开写:

    package com.test.factory;
    
    public class CountTest {
    
        public static void main(String []args) {
            CountTest test = new CountTest();
            test.count("性别");
            test.count("年龄段");
            test.count("居住地");
        }
    
        public void count(String type) {
            if(type.equals("性别")) {
                System.out.println("我是根据<性别>产生的统计数据");
                return;
            }
            if(type.equals("年龄段")) {
                System.out.println("我是根据<年龄段>产生的统计数据");
                return;
            }
            if(type.equals("居住地")) {
                System.out.println("我是根据<居住地>产生的统计数据");
                return;
            }
        }
    }
    

    分析代码利弊

    • 优势:快速,写完上述代码可能你就花了2分钟。

    • 劣势:扩展性不强,当客户方再提出需要根据证件类型统计等需求呢!当其中一个统计逻辑发生修改时,我们都得去修改count方法,这时候我们就应该思考当应用的需求改变时,在不修改原有代码的前提下,如何扩展模块的功能使其满足新的需求。

    使用场景
    扩展性要求不高的功能模块

  2. 简单工厂实现(又称静态工厂),顾名思义有一个工厂类,且工厂类里面是有静态方法,静态方法应该是用来创建一系列产品的(性别统计、年龄段统计、居住地),这些产品都需要进行统计的操作,如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。

    package com.test.factory;
    
    public class StaticFactoryTest {
        public static void main(String []args) {
            CountFactory.create("性别").count();
            CountFactory.create("年龄段").count();
            CountFactory.create("居住地").count();
            CountFactory.create("证件类型").count();
        }
    }
    
    //抽象接口
    interface CountProduct {
    	//产品行为
        void count();
    }
    
    //实现类
    class 性别 implements CountProduct{
    
        @Override
        public void count() {
            System.out.println("我是根据<性别>产生的统计数据");
        }
    }
    
    //实现类
    class 年龄段 implements CountProduct{
    
        @Override
        public void count() {
            System.out.println("我是根据<年龄段>产生的统计数据");
        }
    }
    
    //实现类
    class 居住地 implements CountProduct{
    
        @Override
        public void count() {
            System.out.println("我是根据<居住地>产生的统计数据");
        }
    }
    
    //实现类
    class 证件类型 implements CountProduct{
    
        @Override
        public void count() {
            System.out.println("我是根据<证件类型>产生的统计数据");
        }
    }
    
    //简单工厂
    class CountFactory {
    	//工厂方法
        public static CountProduct create(String type){
            CountProduct product = null;
            switch (type) {
                case "性别" :
                    product = new 性别();
                    break;
                case "年龄段" :
                    product = new 年龄段();
                    break;
                case "居住地" :
                    product = new 居住地();
                    break;
                case "证件类型" :
                    product = new 证件类型();
                    break;
            }
            return product;
        }
    }
    

    分析代码利弊

    • 优势:有了一定的扩展性,并且将产品的创建和业务逻辑给分离开了。

    • 劣势:一旦添加新产品就不得不修改工厂逻辑,同样破坏了软件设计的“开闭原则”。

    使用场景
    1.工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
    2.实际生产中,我们也可以修改工厂中的create方法通过配置文件的方式去配置type和产品的关系,这样我们就可以不同改变创建产品的方法了。
    3.静态工厂也可以根据我们的实际使用进行变形,我们可以在工厂类中有多个创建产品的方法,去创建不同的产品,这样我们也就不需要条件去判断了,符合软件设计的“单一职责原则”。

  3. 工厂方法实现,就是我们常说的工厂模式,静态工厂中添加新的产品时候,获取产品的工厂逻辑需要修改,来看下我们怎么通过工厂方法的方式避免吧!

    package com.test.factory;
    
    public class MethodFactoryTest {
    
        public static void main(String []args) {
            CountFactory 性别factory = new 性别Factory();
            性别factory.createProduct().count();
            CountFactory 年龄段factory = new 年龄段Factory();
            年龄段factory.createProduct().count();
        }
    }
    
    //产品抽象
    interface CountProduct {
        void count();
    }
    
    //真实产品
    class 性别 implements com.test.factory.CountProduct {
    
        @Override
        public void count() {
            System.out.println("我是根据<性别>产生的统计数据");
        }
    }
    
    //真实产品
    class 年龄段 implements com.test.factory.CountProduct {
    
        @Override
        public void count() {
            System.out.println("我是根据<年龄段>产生的统计数据");
        }
    }
    
    //工厂抽象
    interface CountFactory {
         CountProduct createProduct();
    }
    
    //具体工厂
    class 性别Factory implements CountFactory {
        @Override
        public CountProduct createProduct() {
            return (CountProduct) new 性别();
        }
    }
    
    //具体工厂
    class 年龄段Factory implements CountFactory {
        @Override
        public CountProduct createProduct() {
            return (CountProduct) new 年龄段();
        }
    }
    

    分析代码利弊

    1.优势:使用者只需知道创建产品的工厂名,而不知道具体的产品名,添加新的产品的时候,只需添加相应产品类和工厂类,不影响其他代码。

    2.劣势:代码复杂度提升,对于系统中存在不同的产品树没法解决(抽象工厂模式解决)。

    使用场景
    扩展性要求高的功能模块

为什么使用工厂模式?

在实际需求中许多功能模块随着迭代的过程越来越细化。工厂模式能做到软件对象的生产和使用相分离,在满足“开闭原则”的前提下,可以满足客户随意增删或改变对软件相关对象的使用,从而提高代码的可维护性上,可扩展性。

总结

文章至此,有没有感觉工厂模式有点熟悉,是的,我们常用的spring框架中就有工厂模式的应用,在Spring中有两个最基本的工厂,BeanFactory和ApplicationContext。BeanFactory是Spring框架的基础设施,面向的是Spring本身,也就是用于创建Spring扩展的其他内容,如Spring Security、Spring JDBC等,而ApplicationContext这个工厂是面向开发者的,也就是应用上下文——配置文件等,开发者能够使用这个工厂实现自己的功能。
工厂模式的思想正好契合Spring IOC的设计思想:某一接口的具体实现类的选择控制权从调用类中移除,转而交给第三方决定,即借由Spring的Bean配置来实现控制,这同样也是工厂模式的思想。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值