java的23种设计模式02-创建型模式01-工厂方法

一、创建型模式

创建型模式关注点是如何创建对象,其核心思想是要把对象的创建和使用相分离,这样使得两者能相对独立地变换。

创建型模式包括:

  • 工厂方法:Factory Method
  • 抽象工厂:Abstract Factory
  • 建造者:Builder
  • 原型:Prototype
  • 单例:Singleton

二、工厂方法

2-1、工厂方法的定义

工厂方法是指:定义工厂接口和产品接口,但如何创建实际工厂和实际产品被推迟到子类实现,从而使调用方只和抽象工厂与抽象产品打交道。

工厂方法的目的是使得创建对象和使用对象是分离的,并且客户端总是引用抽象工厂和抽象产品

2-2、工厂方法的示例

示例:假设我们希望实现一个解析字符串到Number的Factory,可以定义如下:

1、工厂抽象接口:

public interface NumberFactory {
    Number parse(String s);
}

2、有了工厂接口,再编写一个工厂的实现类:

public class NumberFactoryImpl implements NumberFactory {
    public Number parse(String s) {
        return new BigDecimal(s);
    }
}

抽象工厂:NumberFactory,实际工厂:NumberFactoryImpl;

抽象产品:Number,实际产品:BigDecimal。

因为,在客户端中,我们只需要和工厂接口NumberFactory以及抽象产品Number打交道,所以,客户端如何创建NumberFactoryImpl呢?

通常我们会在接口Factory中定义一个静态方法getFactory()来返回真正的子类:

public interface NumberFactory {
    // 创建方法:
    Number parse(String s);

    // 获取工厂实例:
    static NumberFactory getFactory() {
        return impl;
    }

    static NumberFactory impl = new NumberFactoryImpl();
}

这样,我们就能在客户端如下调用:

NumberFactory factory = NumberFactory.getFactory();
Number result = factory.parse("123.456");

只和抽象工厂:NumberFactory,抽象产品:Number,打交道!

调用方可以完全忽略真正的工厂NumberFactoryImpl和实际的产品BigDecimal。

这样做的好处是允许创建产品的代码独立地变换,而不会影响到调用方。

实际上大多数情况下我们并不需要抽象工厂,而是通过静态方法直接返回产品,即:

// 抽象工厂
public class NumberFactory {
    // 静态方法直接返回实际产品,跳过实际工厂
    public static Number parse(String s) {
        return new BigDecimal(s);
    }
}

这种简化的使用静态方法创建产品的方式称为静态工厂方法。

此时客户端的调用:

Number result = NumberFactory.parse("123.11");

2-3、静态工厂方法

静态工厂方法广泛地应用在Java标准库中。例如:

Integer n = Integer.valueOf(100);

Integer既是产品又是静态工厂。

它提供了静态方法valueOf()来创建Integer。那么这种方式和直接写new Integer(100)有何区别呢?我们观察valueOf()方法:

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

它的好处在于,valueOf()内部可能会使用new创建一个新的Integer实例,但也可能直接返回一个缓存的Integer实例。

对于调用方来说,没必要知道Integer创建的细节。

工厂方法可以隐藏创建产品的细节,且不一定每次都会真正创建产品,完全可以返回缓存的产品,从而提升速度并减少内存消耗。

如果调用方直接使用Integer n = new Integer(100),那么就失去了使用缓存优化的可能性。

2-4、小结

工厂方法是指定义工厂接口和产品接口,但如何创建实际工厂和实际产品被推迟到子类实现,从而使调用方只和抽象工厂与抽象产品打交道。

实际更常用的是更简单的静态工厂方法,它允许工厂内部对创建产品进行优化。

调用方尽量持有接口或抽象类,避免持有具体类型的子类,以便工厂方法能随时切换不同的子类返回,却不影响调用方代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值