Java设计模式——工厂模式_java工厂设计模式-程序员宅基地

技术标签: java  设计模式  开发语言  

设计模式系列文章


前言

最近在学习一些Java设计模式的概念,设计模式诞生的目的,我认为是可以使得写出的代码具有更好的逻辑性,减少了大量冗余代码来进行重复而繁琐的操作,也更好的提升了复用性。所以学习并且能够使用合理的设计模式可以让我们的代码更加美观,优雅,结构更加清晰。

本次内容对Java中的工厂模式进行讲解,工厂模式又可以分为三种

                              ” 简单工厂,工厂方法, 抽象工厂 ”


一、简单工厂模式

工厂模式,主要用于创建对象时的一系列操作。

在我们平时创建对象的时候,一般使用New关键字来进行创建。

ClassA a = new ClassA();
ClassB b = new ClassB();

 我们使用New关键字创建对象,会根据括号内的参数在构造函数里对实例化对象进行初始化。

然而,我们创建一个对象的时候,可能需要对他进行一些初始化操作,例如查询数据库,对属性赋值等等。如果我们把这些操作也全部写到构造函数中。那构造函数就变得很长很长,可读性大大降低。

针对这种情况,我们可以引入 ” 工厂 “ 的概念,我们不通过New关键字去创建对象了,我们直接去创建一个工厂,让工厂去帮我们创建对象。

例如,我们创建了一个专门生产手机的工厂,这个工厂可以生产梨子手机,菠萝手机。

那么首先我们要创建梨子手机和菠萝手机这两个类,这里我实现了一个Phone接口,表明梨子手机和菠萝手机都是一个 ” Phone “类型的类,然后我们在创建的时候返回Phone类型的就可以了。

public interface Phone {
    void show();
}

public class LiPhone implements Phone {
    @Override
    public void show() {
        System.out.println("我是梨子手机");
    }
}

public class BoPhone implements Phone {
    @Override
    public void show(){
        System.out.println("我是菠萝手机");
    }

}

 然后我们再创建一个手机工厂,来生产手机。

这里应该很通俗易懂,我们再创建手机的时候,只需要给定规定好的number,工厂就知道该生产什么手机了,然后也可以按照我们的意愿去进行初始化。

public class PhoneFactory{

    public Phone createPhone(Integer number) {
        Phone phone = null;
        if(number == 1){
            phone = new LiPhone();
            // .....
            // 梨子手机的初始化代码
        }else if(number == 2){
            phone =  new BoPhone();
            // .....
            // 菠萝的初始化代码
        }
        return phone;
    }
}

然而这么做其实又会衍生出一个问题,那就是当我们有很多牌子手机的时候,比如我们还有锤子手机,番茄手机,土豆手机。那我们每多一个手机,就要去修改一次手机工厂的 if else 判断,这违背了设计模式的一个原则 “ 对修改关闭,对拓展开启 ”

(注:所谓面向对象的开放-封闭原则,就是在程序中对“扩展”开放,对“修改”封闭。如果每次业务改动都要增加新的if-else,就涉及对旧有代码的修改,不但容易出错,可读性也不好。)

那么怎么解决呢,我们可以使用下面提到的工厂方法模式。

二、工厂方法模式

前面我们提到,为了解决简单工厂模式中通过工厂创建对象 if esle 语句过多的问题可以使用工厂方法模式。而工厂方法模式的主要原理就是,我们把每一个要创建的产品对象独立分配一个工厂,提取一个工厂接口出来,独立分配的工厂作为工厂接口的实现类,这样我们在创建工厂——再通过工厂创建对象的过程中,工厂就是唯一确定了的,所以创建的对象也是唯一确定的,不需要再使用过多的判断语句了。

所以我们对之前的工厂类进行修改先.

现在我们提取出了一个工厂接口,接口中有生产手机的方法,然后我们为梨子手机和菠萝手机都创建一个工厂类去实现接口,在实现类的 createPhone 方法中创建手机,这样如果我们以后有了其他手机,只需要再增加手机的工厂类去实现接口就可以了。

public interface PhoneFactory {
    Phone createPhone();
}

public class LiFactory implements PhoneFactory{

    @Override
    public Phone createPhone() {
        Phone phone =  new LiPhone();
        // .....
        // 初始化代码
        return phone;
    }
}

public class BoFactory implements PhoneFactory{

    @Override
    public Phone createPhone() {
        Phone phone =  new BoPhone();
        // .....
        //  初始化代码
        return phone;
    }
}

测试方法

public class Test {

    public static void main(String[] args) {
        PhoneFactory factoryA = new LiFactory();
        PhoneFactory factoryB = new BoFactory();
        Phone phoneA = factoryA.createPhone();
        Phone phoneB = factoryB.createPhone();
        phoneA.show();
        phoneB.show();
    }
}

 输出:

我是梨子手机

我是菠萝手机

那么, 其实我们可以显而易见的发现,工厂方法模式虽然可以确保我们每一个手机对应一个工厂,而且需要创建手机的时候只需要通过对应工厂创建就可以了,但是这样随着我们的产品越来越多,工厂的实现类也越来越多,看的人头都晕了。

那么,我们可以使用 “ 抽象工厂 ”模式来解决这个问题。比如我们的梨子手机和菠萝手机分别来自梨子厂和菠萝厂。那梨子厂和菠萝厂它们也有远大的理想!!他们不想只做手机! 他们要搞吧来福,搞把AK,做大做强!

梨子厂要做手机和电脑,菠萝见状,心想那我指定也得卷起来啊,于是菠萝老板下令,我们也要做手机和电脑!

三、抽象工厂模式

从上面的情景我们可以分析得到,梨子厂和菠萝厂都不甘现状,他们不禁想做手机,还想做电脑。

那我们需要去创建一个手机厂的同时再去创建一个电脑厂吗??

那当然不需要了,我们可以创建一个工厂接口,这个工厂既可以做手机,又可以做电脑

我们再创建实现类工厂,梨子厂和菠萝厂。因为梨子厂和菠萝厂都实现了工厂接口,所以他们都有创建手机和电脑的流水线(方法)

那就简单了,我们在各自的流水线中创建自己的产品不就行了嘛

直接上代码!!

哦不 先上个图 画的丑陋,帅哥美女们将就看看

上代码!!!

首先安排两个产品的接口,手机接口和电脑接口,以及他们的实现类。

public interface Phone {
    void showPhone();
}

public class LiPhone implements Phone {
    @Override
    public void showPhone(){
        System.out.println("我是梨子手机");
    }
}

public class BoPhone implements Phone {
    @Override
    public void showPhone(){
        System.out.println("我是菠萝手机");
    }
}

public interface Computer {
    void showComputer();
}

public class LiComputer implements Computer {
    @Override
    public void showComputer() {
        System.out.println("我是梨子电脑");
    }
}

public class BoComputer implements Computer {
    @Override
    public void showComputer() {
        System.out.println("我是菠萝电脑");
    }
}

然后再安排一下我们的重头戏,抽象工厂。

public interface IFactory {
    //创建口罩
    Phone createPhone();
    //创建防护服
    Computer createComputer();
}

public class LiFactory implements IFactory {
    @Override
    public Phone createPhone() {
        Phone phone =  new LiPhone();
        // .....
        //  初始化代码
        return phone;
    }

    @Override
    public Computer createComputer() {
        Computer computer =  new LiComputer();
        // .....
        // 初始化代码
        return computer;
    }
}

public class BoFactory implements IFactory {
    @Override
    public Phone createPhone() {
        Phone phone =  new BoPhone();
        // .....
        //  初始化代码
        return phone;
    }

    @Override
    public Computer createComputer() {
        Computer computer =  new BoComputer();
        // .....
        // 初始化代码
        return computer;
    }
}

 最后测试一下来看看

public class Test {

    public static void main(String[] args) {
        IFactory factoryA = new LiFactory();
        IFactory factoryB = new BoFactory();
        //创建低端口罩
        Phone phoneA = factoryA.createPhone();
        //创建高端口罩
        Phone phoneB = factoryB.createPhone();
        //创建低端防护服
        Computer computerA = factoryA.createComputer();
        //创建高端防护服
        Computer computerB = factoryB.createSuit();

        phoneA.showPhone();
        phoneB.showPhone();
        computerA.showComputer();
        computerB.showComputer();
    }
}

 输出:

我是梨子手机

我是菠萝手机

我是梨子电脑

我是菠萝电脑

大功告成~  


总结

现在越来越多Java开发方面的工作在招聘的要求上都会要求应聘者要熟知常见的设计模式,以及在面试的过程中也经常会问道设计模式相关的知识,所以设计模式的学习是非常重要的,而且学习了还要会融会贯通,在写代码的时候,遇到有重复的代码就可以思考一下是否可以将重复的代码抽取出来进行封装或者其他操作。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_56032340/article/details/123574551

智能推荐

基于Java在线电影票购买系统设计实现(源码+lw+部署文档+讲解等)-程序员宅基地

文章浏览阅读4.1k次,点赞2次,收藏4次。社会和科技的不断进步带来更便利的生活,计算机技术也越来越平民化。二十一世纪是数据时代,各种信息经过统计分析都可以得到想要的结果,所以也可以更好的为人们工作、生活服务。电影是生活娱乐的一部分,特别对喜欢看电影的用户来说是非常重要的事情。把计算机技术和影院售票相结合可以更符合现代、用户的要求,实现更为方便的购买电影票的方式。本基于Java Web的在线电影票购买系统采用Java语言和Vue技术,框架采用SSM,搭配MySQL数据库,运行在Idea里。

集合的addAll方法--list.addAll(null)会报错--java.lang.NullPointerException-程序员宅基地

文章浏览阅读1.8k次。Exception in thread "main" java.lang.NullPointerException at java.util.ArrayList.addAll(ArrayList.java:559) at com.iflytek.epdcloud.recruit.utils.quartz.Acool.main(Acool.java:16)import java.u..._addall(null)

java获取当天0点到24点的时间戳,获得当前分钟开始结束时间戳_java 获取某分钟的起止时间戳-程序员宅基地

文章浏览阅读4.5k次。public static void main(String[] args) { Calendar todayStart = Calendar.getInstance(); todayStart.set(Calendar.HOUR_OF_DAY, 0); todayStart.set(Calendar.MINUTE, 0); toda..._java 获取某分钟的起止时间戳

北京内推 | 京东AI研究院计算机视觉实验室招聘三维视觉算法研究型实习生-程序员宅基地

文章浏览阅读1.1k次。合适的工作难找?最新的招聘信息也不知道?AI 求职为大家精选人工智能领域最新鲜的招聘信息,助你先人一步投递,快人一步入职!京东 AI 研究院京东 AI 研究院(https://air.jd..._京东计算机视觉实验室

Ubuntu18.04安装配置Qt5.15_ubuntu安装qt5.15-程序员宅基地

文章浏览阅读2.1k次。Ubuntu18.04安装配置Qt5.15 Ubuntu18.04安装配置Qt5.15 Qt选择下载Qt安装Qt5.15.0配置后记 Qt选择 在官方的声明中,Qt5.15是Qt5.x的最后一个LTS版本,增加了即将在2020年底推出的Qt6的部分新特性,为了之后的新_ubuntu安装qt5.15

针对Error: You must either define the environment variable DJANGO_SETTINGS_MODULE ...问题的解决_project structure->facets->django->-程序员宅基地

文章浏览阅读1.8w次,点赞5次,收藏3次。针对Error: You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings问题的解决使用intelliJ Idea开发django项目,启动 manage.py 测试时,会出现如上所示问题。根据提示,有两种解_project structure->facets->django->

随便推点

网络安全实验---防火墙实验-程序员宅基地

文章浏览阅读2w次,点赞13次,收藏82次。文章目录一、实验目的:二、实验环境:三、实验内容:1. 安装天网防火墙2. 使用天网防火墙进行实验3.在上端的菜单栏最左边点击应用程序规则,点击下方需要修改应用的选项可以对其进行流量控制4.调节ip规则配置,将“允许自己ping探测其他机器”改为禁止,查看能否再次收到reply5.添加一条禁止邻居同学主机的FTP连接规则四、心得体会:五.软件共享一、实验目的:通过实验深入理解防火墙的功能和工作原理熟悉天网防火墙个人版的配置和使用二、实验环境:一台xp虚拟机和一台windows10虚拟机在xp上安_防火墙实验

vue项目运行报错:94% asset optimization ERROR Failed to compile with 2 errors13:03:01 error in ./src/ba-程序员宅基地

文章浏览阅读6.7k次。使用vue编写的前端项目运行报错:88% hashing 89% module assets processing 90% chunk assets processing 94% asset optimization ERROR Failed to compile with 2 errors13:03:01 error in ./src/base/components/head..._94% asset optimization

适用于 Linux 的 Windows 子系统安装指南 (Windows 10) (微软官方文档)_hyper-v-vmms 虚拟硬盘文件必须是未压缩和未加密的文件,并且不能是稀疏文件。-程序员宅基地

文章浏览阅读2.2k次,点赞2次,收藏3次。官方原文档微软官方教程地址:传送门安装适用于 Linux 的 Windows 子系统必须先启用“适用于 Linux 的 Windows 子系统”可选功能,然后才能在 Windows 上安装 Linux 分发版。以管理员身份打开 PowerShell 并运行:dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart安装所选的 Linux 分发版打开 Micro_hyper-v-vmms 虚拟硬盘文件必须是未压缩和未加密的文件,并且不能是稀疏文件。

rufus 一款好用的linux u盘,光盘刻录工具_rufus可以刻录光盘吗-程序员宅基地

文章浏览阅读2.2k次。rufus 一款好用的linux u盘,光盘刻录工具:下载(点击普通下载中的“立即下载”): http://share.cnop.net/file/1806028-401886318_rufus可以刻录光盘吗

用VB.net实现对.ini文件的读写操作的类-程序员宅基地

文章浏览阅读142次。Option Explicit OnModule INI 'INICont.bas Ver 1.0+a INI '==================================================================== 'GetIntFromINI( sectionName , keyName , defaultValue, iniPath ) '..._vb.net 读取ini文件 int

linux集群—负载均衡集群LBC_lbc在程序中是什么-程序员宅基地

文章浏览阅读615次。1 集群的定义集群的出现主要是为了解决单台设备性能不足、效率低下等问题,可以保证业务无中断,总体效率高,适合大型业务。2 集群的分类3 负载均衡集群LBC_lbc在程序中是什么

推荐文章

热门文章

相关标签