logo头像

life is beautiful like sunshine!

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();

    }
}

运行结果:
这里写图片描述

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

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

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

上一篇