轻松看懂java设计模式简单工厂模式

一、什么是简单工厂模式

简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

二、简单工厂模式的角色和职责

1.工厂(Creator)角色简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。

2.抽象(Product)角色简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

3.具体产品(Concrete Product)角色简单工厂模式所创建的具体实例对象

三、简单工厂模式的UML图

sports:抽象角色

Basketball和Football:具体产品角色

sportsFactory:工厂角色

四、简单工厂模式代码

这个例子,用运动作为抽象角色,足球和篮球作为具体的产品角色来讲解,下面看具体代码。

首先我们创建一个抽象类sports,同时有一个运动的方法

public interface Sports {
    /*
     * 运动
     */
    public void play();
}

然后,定义了一个足球类篮球类,同样有运动方法

public class Basketball implements Sports{
    /*
     * 运动
     */
    public void play(){
        System.out.println("打篮球...");
    }
}
public class Football implements Sports{
    /*
     * 运动
     */
    public void play(){
        System.out.println("踢足球啦...");
    }
}

最后写一个工厂类,用来创造足球运动篮球运动

这里创建的方式有很多种方式,我们从简单的开始,逐步优化代码。

4.1、单独创建实例方法

public class SportsFactory {
    /*
     * 获得Basketball类的实例

    public static  Sports getBasketball() {
        return new Basketball();
    }

    /*
     * 获得Football类实例
     */
    public static Sports getFootball() {
        return new Football();
    }
}

这种方法,直接用两个不同的方法直接创建两个实例对象。

4.2、逻辑判断的方式

public class SportsFactory {

    /*
     * getSports方法,获得所有产品对象
     */
    public static Sports getSports(String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        if(type.equalsIgnoreCase("Basketball")) {
            return Basketball.class.newInstance();

        } else if(type.equalsIgnoreCase("Football")) {
            return Football.class.newInstance();
        } else {
            System.out.println("找不到相应的实例化类");
            return null;
        }

    }
}

先传入一个类型参数,然后判断,再用反射的方式返回对象。

前面这两种方式都不是最优的方式,因为他们都违背了开闭原则

开闭原则定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

开放-封闭原则的意思就是说,你设计的时候,时刻要考虑,尽量让这个类是足够好,写好了就不要去修改了,如果新需求来,我们增加一些类就完事了,原来的代码能不动则不动。这个原则有两个特性,一个是说“对于扩展是开放的”,另一个是说“对于更改是封闭的”。面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。这就是“开放-封闭原则”的精神所在。

下面,我们再优化一下。

4.3、反射实现方式

public class SportsFactory {

    /*
     * getSports方法,获得所有产品对象
     */
    public static Sports getSports(String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

        Class Sports = Class.forName(type);
        return (Sports) Sports.newInstance();

    }
}

这种方法,通过反射的方式实现,不管我们还需要扩展什么其他功能都不用再更改这个工厂类的代码了,所以就符合开闭原则了。

五、测试

public class MainClass {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    //方法一测试
//        //实例化一个Basketball
//        Basketball Basketball = new Basketball();
//        //实例化一个Football
//        Football Football = new Football();
//        
//        Basketball.play();
//        Football.play();

        //方法二测试
//        //实例化一个Basketball,用到了多态
//        Sports Basketball = new Basketball();
//        Sports Football = new Football();
//        Basketball.play();
//        Football.play();

//        //实例化一个Basketball
//        Sports Basketball = SportsFactory.playBasketball();
//        Sports Football = SportsFactory.playFootball();
//        Basketball.play();
//        Football.play();

        //方法三测试
        Sports Basketball = SportsFactory.getSports("Basketball");
        Sports Football = SportsFactory.getSports("Football");
        Basketball.play();
        Football.play();

    }
}

运行结果:

六、简单工厂模式应用场景

优点:工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化

缺点:由于工厂类集中了所有实例的创建逻辑,违反了开闭原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;

觉得有用就转发分享一下吧

原文发布于微信公众号 - 好好学java(SIHAIloveJAVA)

原文发表时间:2018-09-02

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏take time, save time

你所能用到的数据结构(八)

十一、不能被应用的理论不是好研究 前面介绍了堆栈的一些小小的理论模型,那么这样一个东西有什么作用呢?实际中不可能有那么一辆停在站台前方堵死的火车的,即使有,也...

28640
来自专栏Python入门

Python正则表达式的简单应用和示例演示

今天小编给大家分享的是Python正则表达式的简单应用和示例演示,将前面学习的Python正则表达式做一个概括。

11720
来自专栏java一日一条

关于 Java 你不知道的十件事

作为Java 控,我们总是对不太可能直接使用,但能使我们更了解 Java 和 Java 虚拟机(Java Virtual Machine,JVM) 的晦涩细节感...

12510
来自专栏青玉伏案

设计模式(十):从电影院中认识"迭代器模式"(Iterator Pattern)

上篇博客我们从醋溜土豆丝与清炒苦瓜中认识了“模板方法模式”,那么在今天这篇博客中我们要从电影院中来认识"迭代器模式"(Iterator Pattern)。“迭代...

211100
来自专栏Petrichor的专栏

什么是:语法糖、语法盐、语法糖精

59550
来自专栏鹅厂优文

Python 工匠:善用变量来改善代码质量

我一直觉得编程某种意义上是一门『手艺』,因为优雅而高效的代码,就如同完美的手工艺品一样让人赏心悦目。

1K100
来自专栏小詹同学

【记录帖】(No.001)从零打卡刷Leetcode

小詹一直觉得自己编程能力不强,想在网上刷题,又怕不能坚持。不知道有木有和小伙伴和小詹一样想找个人一起刷题呢?欢迎和小詹一起定期刷leetcode,每周一周五更新...

13030
来自专栏从流域到海域

《笨办法学Python》 第35课手记

《笨办法学Python》 第35课手记 本节课讲函数和分支的,实际上是一次综合练习,代码有点长,请先纠正代码中的错误使脚本能够运行。 原代码中使用三个空格来进行...

227100
来自专栏zaking's

js算法初窥03(搜索及去重算法)

14020
来自专栏C语言及其他语言

[每日一题]大、小写问题

题目描述 输入一串字符,将其中的大写变成小写,若不为大写则原样输出 输入 任意字符串(长度在100以内)以回车表示输入结束 输出 将其中的大写 输出相应的小写,...

31760

扫码关注云+社区

领取腾讯云代金券