【设计模式】简单工厂

唤起一天明月,照我满怀冰雪

简单工厂不属于GOF23种设计模式,但是能够帮助理解抽象工程等GOF23中的设计模式,它的工厂思想是有关工厂的基本思想,这个思想也是非常常用的,如果加上简单工厂,我们介绍的设计模式有24种

简单工厂模式

简单工厂:又称为“静态工厂方法模式”,属于“类创建型模式”,提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。

模式结构:

  • Api:定义客户所需要的功能接口,也就是抽象的产品类,可以是接口或者抽象类。
  • Impl:具体实现Api的实现类,可能会有多个,具体的产品类。
  • Factory:工厂,选择合适的实现类来创建Api接口对象。
  • Client:客户端,通过Factory来获取Api接口对象,然后面向Api接口编程。

For Example:

场景:你开了一家甜品生产公司,现在开始生产

创建一个抽象的甜品生产类:

package com.ekin.softwaredesign.simplefactory;

/**
 * @Author: ekin
 * @Date: 2021/4/10 9:53
 */
public interface Dessert {
    public void produce();
}

现在要生产甜甜圈:

package com.ekin.softwaredesign.simplefactory;

/**
 * @Author: ekin
 * @Date: 2021/4/10 9:57
 */
public class Doughnut implements Dessert {
    @Override
    public void produce() {
        System.out.println("草莓甜甜圈");
    }
}

又要生产奶酪:

package com.ekin.softwaredesign.simplefactory;

/**
 * @Author: ekin
 * @Date: 2021/4/10 9:58
 */
public class Cheese implements Dessert {
    @Override
    public void produce() {
        System.out.println("奶酪");
    }
}

工厂开始生产:

package com.ekin.softwaredesign.simplefactory;

/**
 * @Author: ekin
 * @Date: 2021/4/10 10:00
 */
public class DessertFactory {
    public Dessert getDessert(String type){
        if("草莓甜甜圈".equals(type)){
            return new Doughnut();
        }else if ("奶酪".equals(type)) {
            return new Cheese();
        }
        return null;
    }
}

测试类:

package com.ekin.softwaredesign.simplefactory;

/**
 * @Author: ekin
 * @Date: 2021/4/10 10:02
 */
public class SfTest {
    public static void main(String[] args) {
        DessertFactory factory = new DessertFactory();
        Dessert dessert = factory.getDessert("草莓甜甜圈");
        if(dessert == null) return;
        dessert.produce();
    }
}

UML图:
在这里插入图片描述
这个例子是最简单的简单工厂模式,从这里可以看出 DessertFactory 就是你所开的甜品生产公司,具体的甜品类型是如何生产出来的,客户端是不需要知道的,这就在一定程度上完成了封装的任务

但这里有个缺点,可以看到我们测试的时候要传入参数,客户需要知道参数相关内容,这表明我们需要暴露给客户一定的内部实现细节,并没有很好的完成封装任务。

接着看,现在你的公司要扩大生产规模,决定添加一个新的甜品类:肉松小贝,这个时候就要创建一个新的具体实现类并去修改 DessertFactory 类,但随着公司规模的日益扩大,最后Factory类就会被频繁的修改,代码也会变得更加复杂,这显然不是一个很好的解决办法,也不符合开闭原则

这个时候我们可以用反射来解决,也就是优化代码

package com.ekin.softwaredesign.simplefactory;

/**
 * @Author: ekin
 * @Date: 2021/4/10 10:00
 */
public class DessertFactory {
    public Dessert getDessert(Class c) {
        Dessert dessert = null;
        try {
            dessert = (Dessert) Class.forName(c.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return dessert;
    }
}

测试:

package com.ekin.softwaredesign.simplefactory;

/**
 * @Author: ekin
 * @Date: 2021/4/10 10:02
 */
public class SfTest {
    public static void main(String[] args) {
        DessertFactory factory = new DessertFactory();
        Dessert dessert = factory.getDessert(Doughnut.class);
        if(dessert == null) return;
        dessert.produce();
    }
}

这样即使新增新的甜品种类,factory也能找到对应的实现类而不需要改变代码

下面我们来看一个具体的实现流程:
在这里插入图片描述
现在我们可以对简单工厂模式作一个总结:

  • 简单工厂的本质是选择实现,重点在选择,实现是已经做好了的,目的在于为客户端来选择相应的实现,从而使得客户端和实现之间解耦。
  • 最大的问题在于 工厂类的职责相对过重 ,增加新的产品需要修改工厂类的判断逻辑,这就与开闭原则相违背。
  • 简单工厂模式的要点在于: “如何选择”实现,上面讲的都是静态参数,还可以是动态参数,比如运行时从内存中读取参数,或者从数据库里读取参数,只要传入正确的参数,工厂就能正常运行,具体的实现细节是不用管的

优点与缺点

优点:

  • 帮助封装:简单工厂虽然很简单,但是非常友好地帮助我们实现了组件的封装,然后让组件外部能真正面向接口编程。
  • 解耦:通过简单工厂,实现了客户端和具体实现类的解耦。如同上面的例子,客户端根本就不知道具体是由谁来实现,也不知道具体是如何实现的,客户端只是通过工厂获取它需要的接口对象。

缺点:

  • 可能增加客户端的复杂度:如果通过客户端的参数来选择具体的实现类,那么就必须让客户端能理解各个参数所代表的具体功能和含义,这样会增加客户端使用的难度,也部分暴露了内部实现,这种情况可以选用可配置的方式来实现。
  • 不方便扩展子工厂:私有化简单工厂的构造方法,使用静态方法来创建接口,也就不能通过写简单工厂类的子类来改变创建接口的方法的行为了。不过,通常情况下是不需要为简单工厂创建子类的。
  • 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
  • 工厂职责过重,一旦出现“故障”,整个系统将都不能正常工作

何时选用

  • 如果想要完全封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选用简单工厂,让客户端通过工厂来获取相应的接口,而无须关心具体的实现。
  • 如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单工厂可以创建很多的、不相关的对象,可以把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制。

简单工厂模式并不难,重点在于使用者如何在日常码字中灵活运用,真正用理论解决实际问题,比如像JDBC,我们日常使用的时候只要加载驱动就行了,但我们点开其代码之后会发现,内部也是一个简单工厂模式,这就很好的完成了封装。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值