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

智能推荐

三维点云处理-KDTree和Octree-程序员宅基地

文章浏览阅读578次,点赞22次,收藏17次。点云数据主要是表征目标表面的海量点集合,并不具备传统实体网格数据的集合拓扑信息。因此,如何建立离散点间的拓扑关系,实现基于邻域关系的快速查找也是点云数据处理中比较核心的问题。对于一维数据来说,典型的树形存储结构如Binary Search Tree(BST),特点在于:对于树中的每个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都大于该节点的值,即中序遍历是有序的。这种结构在执行搜索操作时效率较高,在平均情况下,如果树保持相对平衡,BST 的时间复杂度为 O(log n)。

关于vue-grid-layout vue 可拖拽缩放组件的使用 已经 vue-grid-layout和echarts结合的用法_vue3可拖拽缩放 echarts-程序员宅基地

文章浏览阅读4.1k次,点赞3次,收藏22次。关于vue-gird-layout 的使用方法规范<grid-layout // 网格初始化布局 数组 必填 每一项都必须具有i、x、y、w和h属性 :layout.sync="layout" // 表示网格有多少列 number 类型 非必填 默认为12 :col-num="12" // 表示_vue3可拖拽缩放 echarts

Framebuffer的配置及应用——先转载留着,以后一定要弄懂-程序员宅基地

文章浏览阅读365次。http://blog.csdn.net/tju355/article/details/6881389 借助于framebuffer,我们能够在console下面作很多事情。首先下载framebuffer的配置工具fbset:# apt-get install fbset 下载完毕后,配置文件/etc/fb.modes随之产生。比较简单的作法是用万能的vesafb,如果它被编译进了内核,如:D..._etc/fb.mode

c语言列方程组解方程,求助! C语言用矩阵求解方程组-程序员宅基地

文章浏览阅读100次。该楼层疑似违规已被系统折叠隐藏此楼查看此楼程序在这个邮箱里,行列式的计算没有问题,好像问题出在了把行列式变换上,就是slove(1,n)这个函数的运算上,那位大神可以看看问题到底出在哪…… 不胜感激!!!#include #include void input(int n);void output(int n);double slove(int i , int n);double A[10][1..._c语言怎么列方程

强化学习和序列决策问题的关系-程序员宅基地

文章浏览阅读426次,点赞17次,收藏9次。序列决策问题指代理需要连续地做一系列决策,以达到长期的目标。

输入法开发解析_选择一款你熟悉的输入法软件,提取功能点,谈谈你对输入法开发的认识-程序员宅基地

文章浏览阅读1.5k次。Android平台自1.5版本之后开放了输入法框架(Input Method Framework,IMF),IMF是Android平台的特色设计。它的出现,为诞生不带实体键盘的设备提供了可能。同时,IMF开放了Android平台输入法的开发接口,为Android平台的输入法提供了可扩展性。OPhone平台继承了Android平台的输入法框架。本文首先介绍OPhone平台IMF的构成、工作机制和流程,以便广大开发者能够更好的理解OPhone平台是如何实现文字输入。接下来,将以一个简单的_选择一款你熟悉的输入法软件,提取功能点,谈谈你对输入法开发的认识

随便推点

Nmap介绍及使用-程序员宅基地

文章浏览阅读1.4w次,点赞6次,收藏73次。一、简介1,设计目的:快速扫描大型网络/单个主机。2,如何实现:使用原始IP报文来发现网络上有哪些主机,主机提供什么服务,操作系统,使用什么类型的报文过滤器/防火墙,以及其他功能。3,nmap用途:常用于安全审核。许多系统管理员和网络管理员也用它来做一些日常的工作,比如查看整个网络的信息,管理服务升级计划。4, nmap脚本引擎NSE:可以添加自己的代码,打造自己的工具。nmap是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端。确定哪些服务运行在哪些连接端,并且推断计算机运行..._nmap

linux内核协议栈 邻居协议之通用邻居项的状态机机制【核心】_neigh_add netlink-程序员宅基地

文章浏览阅读1.4k次,点赞2次,收藏16次。1邻居几个核心状态邻居项的状态机机制是通用邻居层最重要的内容,主要是处理邻居项中状态的改变,其中包括几个邻居状态的定时器机制,以及邻居项的更新,solicit请求的发送等对于通用邻居项的状态机,主要有如下几个状态:NUD_INCOMPLETE NUD_REACHABLE NUD_STALE NUD_DELAY NUD_PROBE NUD_FAILED NUD_NOARP NUD_PERMANENT 其中,处于如下状态的邻居项,都会启动一个定时器:#define NUD.._neigh_add netlink

PHP模板引擎-程序员宅基地

文章浏览阅读37次。2019独角兽企业重金招聘Python工程师标准>>> ...

BLE-NRF51822教程13-连接时触发配对_nrf hid 设备不能和同一台电脑连续配对?-程序员宅基地

文章浏览阅读505次。最近答疑碰到几次都提到 需要实现手机每次连接上设备后,立刻出发配对并要求输入密钥的功能。 这里就单独写一个教程供大家参考下。 配对的目的是为了对链路进行加密。以提高蓝牙的传输安全。关于配对的一些相关知识在 静态密码/动态随机密码教程中有一些介绍。对于使用来说,理解一下配对相关流程就行了。 这里额外说个问道比较多的配对和绑定区别的问题:关于配对和绑定,一些人可能一直分不清楚他..._nrf hid 设备不能和同一台电脑连续配对?

Kubernetes网络隔离_serviceaccount/weave-net unchanged-程序员宅基地

文章浏览阅读649次。Kubernetes网络隔离Network Policies隔离手段:NetworkPolicy要在Kubernetes集群中使用NetworkPolicy,CNI网络插件必须维护一个NetworkPolicy Controller,支持Kubernetes 的NetworkPolicy。实现了NetworkPolicy的网络插件包括Weave和Calico等,但不包括Flannel。通过控制循环的方式对NetworkPolicy对象的增删改查作出响应,然后在宿主机上完成iptables规则的配置工作_serviceaccount/weave-net unchanged

如何判定是NR5G 还是LTE_physicalchannelconfig.java-程序员宅基地

文章浏览阅读1k次。RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGPhysicalChannelConfig.javaLTE下radio log搜RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG,查看是否有以下字符串mConnectionStatus=SecondaryServing,mRat=20,有的话就是NSA_physicalchannelconfig.java

推荐文章

热门文章

相关标签