简单工厂模式

简单工厂模式

  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.如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单工厂可以创建很多的、不相关的对象,可以把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值