Java设计模式之简单工厂模式

来源:互联网 发布:sql数据库远程连接 编辑:程序博客网 时间:2024/05/29 12:46

什么是简单工厂模式

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

模式中包含的角色及其职责

  1. 工厂(Creator)角色

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

  2. 抽象(Product)角色

    简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

  3. 具体产品(Concrete Product)角色

    简单工厂模式所创建的具体实例对象

上面的定义可能不容易理解,我们举例子来一步一步的说明简单工厂模式是如何实现的。

1、原始实现

定义两个实体类,一个是苹果类,一个是香蕉类,然后在 Main 方法中通过 new 生成他们对应的实例,通过 实例.方法名称 去调用他们对应的方法。

public class Apple {    public void get(){        System.out.println("摘苹果");    }}public class Banana {    public void get(){        System.out.println("摘香蕉");    }}public class Main {    public static void main(String[] args) {        Apple apple = new Apple();        Banana banana = new Banana();        apple.get();        banana.get();    }}

2、改进实现一

这是最基本的写法,我们观察到苹果和香蕉都有相同的 get 方法,因此我们决定新建一个 Fruit 类作为父类,让 Apple 和 Banana 去分别实现父类中的方法,于是就有了下面的写法。

public interface Fruit {    void get();}public class Main {    public static void main(String[] args) {        Fruit apple = new Apple();        Fruit banana = new Banana();        apple.get();        banana.get();    }}public class Apple implements Fruit {    public void get(){        System.out.println("摘苹果");    }}public class Banana implements Fruit{    public void get(){        System.out.println("摘香蕉");    }}

上面的代码很明显用到了多态,在 Main Class 中的这样两行代码

Fruit apple = new Apple();

Fruit banana = new Banana();

很明显,父类的引用指向了子类的对象。基于上面的写法,我们还能不能进一步进行修改呢?答案是 yes 。下面我们在对上面的代码进行进一步的修改。

3、改进实现二

我们新建一个工厂类,这个工厂类主要负责产生对应的实例

public class FruitFactory {    public static Fruit getApple(){        return new Apple();    }    public static Fruit getBanana(){        return new Banana();    }}public class Main {    public static void main(String[] args) {          //通过工厂来产生对应的实例        Fruit apple = FruitFactory.getApple();        Fruit banana = FruitFactory.getBanana();        apple.get();        banana.get();    }}

其他的类我就不贴出来了,和上面的一样,这里我们主要是对 FruitFactory 进行改进。

4、改进实现三

根据上面的情况,我们看看 FruitFactory 还有没有什么需要改进的地方呢? 应该是有的,是吧。我们接下来对工厂进行进一步的改进。

提供一个 get 方法,通过传入的 type 来决定生产什么样的对象。public class FruitFactory {    public static Fruit get(String type) throws IllegalAccessException, InstantiationException {        if(type.equalsIgnoreCase("apple")){            return Apple.class.newInstance();        }else if(type.equalsIgnoreCase("banana")){            return Banana.class.newInstance();        }else{            throw new RuntimeException("找不到对应的实例生成");        }    }}public class Main {    public static void main(String[] args) throws InstantiationException, IllegalAccessException {        Fruit apple = FruitFactory.get("apple");        Fruit banana = FruitFactory.get("banana");        apple.get();        banana.get();    }}

上面的这种写法比较灵活,但是缺点也很明显,比如如果我现在想要新增一个梨子对象,我们必须要修改 FruitFactory 中的 if else 语句才能通过工厂产生梨子对象,这显然是不合乎要求的。我们可以对 FruitFactory 在进行更好的优化。

public class FruitFactory {    pubilc static Fruit get(String type) throws ClassNotFoundException, IllegalAccessException, InstantiationException {        Class fruit = Class.forName(type);        return (Fruit) fruit.newInstance();    }}public class Main {public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {        Fruit apple = FruitFactory.get("com.selfassu.factory.Apple");        Fruit banana = FruitFactory.get("com.selfassu.factory.Banana");        apple.get();        banana.get();    }}

这里我们通过 Class.forName(完整类名) 去动态生产不同的对象,这里的原理就是反射。我们的简单工厂模式到这里就结束了,可以观察一下每一个 FruitFactory 中的 get 方法,三次均是不同的,我们对 get 方法经过了 三次不同的改造,从适用性来看,最后一种是最好的。

假如我们现在要添加一个新的类型 – 梨子

首先我们新建一个 Pear 类,它实现了 Fruit 接口

按照第一个工厂
我们必须在工厂中添加一个 getPear() 方法,然后返回一个 Fruit 对象。

按照第二个工厂
我们需要在 FruitFactory 中的 get() 方法中添加 一个 if else 语句。

按照第三个工厂
我们不需要对工厂做任何的改动,只需要通过调用 FruitFactory 的 get() 方法传入 Pear 类的全路经即可生成对应的对象。这样很好的实现了对扩展开放,对修改闭合的原则。也就是我们常说的开闭原则

综合上面所描述的,可扩展性和适用性一目了然。当然第三种也有它自己的缺陷,比如 get() 方法传入的类型必须是类的全路径,而第二种就不需要传入全路径名。

简单工厂模式的优缺点

在这个模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。

不难发现,简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以“高内聚”方面做的并不好。另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做相应的修改,扩展性并不很好。

0 0