专栏首页晏霖工厂模式

工厂模式

前言

在23中设计模式中,工厂方法属于创建型的设计模式,只有工厂方法和抽象工厂两种,但是实际我们常与简单工厂混淆,因为简单工厂模式违背了开闭原则。

什么是开闭原则:开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

所以简单工厂不属于设计模式内的,但是并不是说简单工厂是错误的,只是根据具体情况使用而已。

下面我就针对简单工厂、工厂方法、抽象工厂结合Demo演示给大家。

正文

如图,就是工厂模式的划分。

简单工厂

概念:一个工厂类根据传入的参量决定创建出那一种产品类的实例。

想象一下汽车生产厂生产汽车,有两个工厂,分别是宝马和奔驰,客户想要买这两种车,就要分别去这两个工厂去买,结合在代码里就是客户分别传递不同的参数才可以得到不同的对象。

首先我们需要一个接口,用来返回不同的品牌的汽车。

public interface Car {
    void produce();
}

然后我们需要两个汽车

public class Benz implements Car {
    public void produce() {
        System.out.println("生产一辆奔驰");
    }
}
public class BMW implements Car {
    public void produce() {
        System.out.println("生产一辆宝马");
    }
}

接下来就是工厂,这个工厂就是根据客户传过来的不同参数返回不同的汽车。

public class CarFactory {
    public Car produce(String type) {
        if ("bmw".equals(type)) {
            return new BMW();
        } else if ("benz".equals(type)) {
            return new Benz();
        } else {
            System.out.println("类型错误");
        }
        return null;
    }
}

最后来了一个顾客说是要买宝马,让我们来测试一下吧

public class SimpleFactoryTest {
    public static void main(String[] args) {
        CarFactory factory = new CarFactory();
        Car car = factory.produce("bmw");
        car.produce();
    }
}

大家看代码可以得知,现在是两个车,就要写两个if去判断,如果以后出现很多个产品那么就就要在工厂方法里写多个if ,这样就会造成拓展业务需要修改原有代码来实现,这样的写法可以实现,但是很low,建议同学们尝试以下两种。

工厂方法模式

概念:定义一个创建对象的接口,让子类决定实例化那个类。

工厂模式细分的话有两种,我在代码里会讲解一种,另一种在示例代码中体现,被我注释掉的就是普通工厂方法,大家一看便知。

与简单工厂重复的代码我就贴在一个代码块中了。

public interface Car {
    void produce();
}

public class Benz implements Car {
    public void produce() {
        System.out.println("生产一辆奔驰");
    }
}

public class BMW implements Car {
    public void produce() {
        System.out.println("生产一辆宝马");
    }
}

不同的地方就是工厂的写法,我们一个汽车品牌就新建一个工厂方法。

public class BenzCarFactory {
    /**
     * 工厂方法
     * @return
     */
//    public Car produceBenz() {
//        return new Benz();
//    }

    /**
     * 静态工厂方法
     *
     * @return
     */

    public static Car produceBenz() {
        return new Benz();
    }
}
public class BMWCarFactory {
    /**
     * 工厂方法
     * @return
     */
//    public Car produceBMW() {
//        return new BMW();
//    }
    
    /**
     * 静态工厂方法
     *
     * @return
     */
    public static Car produceBMW() {
        return new BMW();
    }
}

因为只静态的方法,那么在jvm加载时就已经创建了,所以我们在引用的时候就不用new工厂对象了,这也是普通工厂方法与静态工厂方法的区别所在。

让我们看一下客户是怎么购买汽车的。

public class FactoryMethodTest {
    //psvm
    public static void main(String[] args) {
        /**
         * 工厂方法
         */
//        BenzCarFactory factory = new BenzCarFactory();
//        Car car = factory.produceBenz();
//        car.produce();

        /**
         * 静态工厂方法
         */
        Car car = BenzCarFactory.produceBenz();
        car.produce();
    }
}

可以看出,每个工厂只生产一种产品,客户端通过不同的工厂去生产不同的产品。这样做的好处就是我们对业务进行拓展时不用更改代码,只需要新增一个拓展对产品或者对象就可以,这也是最简单也是我认为最常用对工厂方法了。

抽象工厂

概念:创建相关或依赖对象的家族,而无需明确指定具体类。

抽象工厂适用于复杂业务需求,复杂的产品生产场景中。怎么复杂呢?就是产品属性多了一个纬度,之前我们都是生产汽车,但是现在要区分出生产的颜色,对汽车的要求不仅仅是品牌还有颜色了。

来看看具体的代码实现:

首先定义三种颜色的接口

public interface Black {
    void create();
}

public interface Red {
    void create();
}


public interface White {
    void create();
}

然后定义我们存在的产品,我们现在只有黑色奔驰,黑色宝马,白色奔驰,白色宝马,红色奥迪。分别创建这五个产品的类。

public class BenzBlack implements Black {
    public void create() {
        System.out.println("黑色奔驰");
    }
}

public class BenzWhite implements White {
    public void create() {
        System.out.println("白色奔驰");
    }
}


public class BMWBlack implements Black {
    public void create() {
        System.out.println("黑色宝马");
    }
}

public class BMWWhite implements White {
    public void create() {
        System.out.println("白色宝马");
    }
}

public class RedAudi implements Red {
    public void create() {
        System.out.println("红色奥迪");
    }
}

然后我们定义工厂接口,工厂接口是把刚才颜色接口进行了统一整理在一起。说明我们现在可以生产这三种颜色任意品牌汽车。

所以说对业务拓展性非常高。

public interface CarFactory {
    Black black();

    White white();

    Red red();
}

那么就让我们随意创建三种汽车的工厂。

public class AudiFactory  implements CarFactory{
    public Black black() {
        return null;
    }

    public White white() {
        return null;
    }

    public Red red() {
        return new RedAudi();
    }
}

public class BenzFactory implements CarFactory {
    
    public Black black() {
        return  new BenzBlack();
    }

    public White white() {
        return new BenzWhite();
    }

    public Red red() {
        return null;
    }
}

public class BMWFactory implements CarFactory {
    public Black black() {
        return new BMWBlack();
    }

    public White white() {
        return new BMWWhite();
    }

    public Red red() {
        return null;
    }
}

让我们来测试一下

public class AbstractFactoryMethodTest {
    public static void main(String[] args) {
        AudiFactory audi = new AudiFactory();
        Red redAudi = audi.red();
        redAudi.create();

        BenzFactory benz = new BenzFactory();
        Black blackBenz = benz.black();
        blackBenz.create();

    }
}

输出结果如下

如果要对以上代码有疑问,或者想要代码,可以加我微信 15524579896

总结

简单工厂模式适用于工厂类需要创建的对象比较少的情况,客户只需要传入具体的参数,就可以忽略工厂的生产细节,去获取想要的对象;

工厂方法模式,主要是针对单一产品结构的情景,拓展时只需增加一个工厂类就可以;

抽象工厂模式则是针对多级产品结构(系列产品)的一种工厂模式,拓展时增加多个类,改动比较大;

最后在说一下,每种模式都有自己的优点和弊端,没有最好的模式,只有最适合的模式,只要符合实际开发需求就是最好的。

本文分享自微信公众号 - 晏霖(yanlin199507),作者:晏霖

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-02-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring Cloud Turbine聚合Hystrix

    前面文章提到了使用了Feign集成的Hystrix做了一个简单的实战练习,成功的进行了服务降级和失败快速返回。下面我要对熔断器监控进行页面化,并将多个服务的的...

    胖虎
  • Spring Cloud Zuul实现多级自定义Filter

    这篇博客不会去介绍关于zuul的基础知识以及配置详解,我会以代码的形式一步一步带领大家实现,利用多种或一种不同类型的过滤器进行处理相应的业务,以便让大家了解各个...

    胖虎
  • SpringBoot统一异常拦截处理

    前言 大家你好! 这是我的第一篇博客 ,我会把我所学所悟的知识以最简单的语言描述清楚,让大家通俗易懂。

    胖虎
  • 抽象工厂模式

    ?原文地址为https://www.cnblogs.com/haixiang/p/12055272.html,转载请注明出处!

    海向
  • Spring Boot 2.X(十八):集成 Spring Security-登录认证和权限控制

    在企业项目开发中,对系统的安全和权限控制往往是必需的,常见的安全框架有 Spring Security、Apache Shiro 等。本文主要简单介绍一下 Sp...

    朝雾轻寒
  • 抽象工厂模式

    抽象工厂中 接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。 在简单工厂中,我们需要一辆车就用CarFact...

    OPice
  • 设计模式学习 - 工厂模式

    根据不同的对象,提供不同的工厂,然后由客户端来选择对应的工厂。这也是与简单工厂模式的不同的地方。

    许杨淼淼
  • ASP.NET Web API中的依赖注入什么是依赖注入ASP.NET Web API依赖解析器使用Unity解析依赖配置依赖解析

    什么是依赖注入     依赖,就是一个对象需要的另一个对象,比如说,这是我们通常定义的一个用来处理数据访问的存储,让我们用一个例子来解释,首先,定义一个领域模型...

    小白哥哥
  • 【java设计模式】之 工厂模式

    使用场景:在任何需要生成复杂对象的地方,都可以使用工厂方法模式。 直接用new可以完成的不需要用工厂模式

    用户5640963
  • Java常用设计模式

    工厂是干嘛的,就是用来生产的嘛,这里说的工厂也是用来生产的,它是用来生产对象的。也就是说,有些对象我们可以在工厂里面生产,需要用时直接从工厂里面拿出来即可,而不...

    贪挽懒月

扫码关注云+社区

领取腾讯云代金券