简单工厂模式

来源:互联网 发布:淘宝推广首选晨昊网络 编辑:程序博客网 时间:2024/05/21 17:45

简单工厂模式

  1. 定义:提供一个创建对象实例的功能, 而无须关心其具体实现,被创建的类型可以是接口、抽象类,也可以是具体类。
简单工厂模式的例子:public interface Fruit {    public void grow();}public class Banana {    @Override    public void grow() {        System.out.println("我是香蕉,我在生长");    }}public class Apple {@Override    public void grow() {        System.out.println("我是苹果,我在生长");    }}public class FruitFactory {    public static Fruit product(String name) {        if ("apple".equals(name)) {            return new Apple();        }        if ("banana".equals(name)) {            return new Banana();        }        return null;    }}public class Client {    public static void main(String[] args) {        Fruit fruit1 = FruitFactory.product("apple");        fruit1.grow();        Fruit fruit2 = FruitFactory.product("banana");        fruit2.grow();    }}

输出结果:

我是苹果,我在生长我是香蕉,我在生长

如果不使用简单工厂模式那么客户端代码会变成这样:

public class Client {    public static void main(String[] args) {        Fruit fruit1 = new Apple();        fruit1.grow();        Fruit fruit2 = new Banana();        fruit2.grow();    }}

在阐述简单工厂模式之前,我们先来回顾一下接口,接口是用来干什么的呢?通常用接口来定义实现类的外观,约定了实现类应该要实现的功能。使用接口的好处:只要接口不变,内部实现的变化就不会影响到外部应用,从而使系统变得更加灵活,具有更好的扩展性和可维护性。而以上代码是直接在客户端new 的实现类,这样大大降低的接口的好处,扩展性和可维护性都变差了,如果系统又增加了一种水果怎么办,需要改代码吗?答案是肯定不是,如果你说那还不是要在FruitFactory中在加一段逻辑,那还不是要改代码呀,不要着急,这里会有其他办法解决的,比如使用配置文件解析,反射等知识点。


静态工厂模式
通常把简单工厂类实现成一个工具类,直接使用静态方法就可以了,也就是说简单工厂的方法都是静态的,所有也被成为静态工厂。

public class FruitFactory {    private FruitFactory() {}    public static Fruit product(String name) {        if ("apple".equals(name)) {            return new Apple();        }        if ("banana".equals(name)) {            return new Banana();        }        return null;    }}

静态工厂类的构造方法为private,因为工厂类只有一个就可以了,所有声明成私有的,这样更加严格。

静态工厂(简单工厂)中方法的写法:主要实现的功能是“选择合适的实现类”来创建实例对象。那如何选择?

  1. 通过配置文件
public static Fruit product() {    Properties p = new Properties();    InputStream in = null;    try {        in = FruitFactory.class.getResourceAsStream("Fruit.properties");        p.load(in);    } catch (IOEception e) {        e.printStackTrace();    } finally {        try {            in.close();        } catch (IOException e) {            e.printStackTrace();        }    }    Fruit fruit = null;    try {        fruit = (Fruit)Class.forName(p.getProperty("fruitClass")).newInstance();    } catch (Exception e) {        e.printStackTrace();    }    return fruit;}//Fruit.properties文件的内容如下:frutiClass=com.yhc.fruitImpl.Apple
  1. 通过Client或者说是形参
//不同的参数返回不同的对象,而参数正是来源于客户端if ("apple".equals(name)) {    return new Apple();}if ("banana".equals(name)) {    return new Banana();}
  1. 通过系统自身,比如运行期间的某个值
FruitFactory类中定义一个静态的私有的变量private static int count = 0;静态方法中这样写:if (count < 5) {    count++;    return new Apple();}if (count >= 5) {    return new Banana();}

注意:第2中方式有一点需要了解的,如果是从客户端调用工厂的时候,传入选择的参数,这就说明客户端必须知道每个参数的含义,也需要知道每个参数对应的功能处理,这就要求必须在一定程度上,向客户端暴露一定的内部实现细节。第一种方式比起第二种方式要好,第一种方式的“选择”体现在配置文件中,系统需要那种对象,我就修改它的全路径类名,而且其还具有可扩展性,如果我再增加一种水果,就只编写类和修改配置文件,其他代码完全不用修改,这就是可插拔性。

简单工厂的优缺点:帮助封装,解耦,可能增加客户端的复杂度,不方便扩展自工厂
简单工厂的本质是:选择实现
何时使用简单工厂:
1.如果想要完全封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选用简单工厂,让客户端通过工厂来获取相应的接口,而无需关心具体实现。
2.如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单工厂可以创建很多的、不相关的对象,可以把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制。

原创粉丝点击