设计模式 工厂方法

目录

 

1.工厂方法

2.静态工厂方法


1.工厂方法

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。

工厂方法即Factory Method,是一种对象创建型模式。

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

package com.learn.factorymethod;

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


---
package com.learn.factorymethod;

public interface NumberFactory extends Factory{
    static NumberFactory impl=new NumberFactoryImpl();

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

---
package com.learn.factorymethod;

import java.math.BigDecimal;

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

在客户端中,我们只需要和工厂接口NumberFactory以及抽象产品Number打交道:

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

调用方可以完全忽略真正的工厂NumberFactoryImpl和实际的产品BigDecimal,这样做的好处是允许创建产品的代码独立地变换,而不会影响到调用方。

2.静态工厂方法

一个简单的parse()需要写这么复杂的工厂吗?实际上大多数情况下我们并不需要抽象工厂,而是通过静态方法直接返回产品,即:

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

这种简化的使用静态方法创建产品的方式称为静态工厂方法(Static Factory Method)。静态工厂方法广泛地应用在Java标准库中。

Integer n = Integer.valueOf(66);

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

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

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

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

package com.learn.factorymethod;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;

public class LocalDateFactory {

    private static Map<Integer, LocalDate> cache=new HashMap<>();

    public static LocalDate fromInt(int yyyyMMdd){
        if(yyyyMMdd >= 20200101 && yyyyMMdd <= 20300101){
            LocalDate result=cache.get(yyyyMMdd);
            if(result == null){
                result=create(yyyyMMdd);
                cache.put(yyyyMMdd,result);
            }
            return result;
        }
        return create(yyyyMMdd);
    }

    public static LocalDate create(int yyyyMMdd){
        return LocalDate.of(yyyyMMdd / 10000,yyyyMMdd / 100%100,yyyyMMdd % 100);
    }
}
package com.learn.factorymethod;

import net.sf.cglib.core.Local;

import java.time.LocalDate;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        NumberFactory factory=NumberFactory.getFactory();
        Number result=factory.parse("123.456");
        System.out.println(result);

        Integer a=66;
        Integer b=66;
        Integer c=128;
        Integer d=128;

        System.out.println(a == b);
        System.out.println(c == d);

        LocalDate ld=LocalDateFactory.fromInt(20200202);
        System.out.println(ld);
        LocalDate ld2=LocalDateFactory.fromInt(20200202);
        System.out.println(ld == ld2);
    }
}

注:

1.总是引用接口而非实现类,能允许变换子类而不影响调用方,即尽可能面向抽象编程。

2.关于Integer.valueOf()方法

JDK在1.5版本中添加的一项新特性,把-128~127的数字缓存起来了,用于提升性能和节省内存。所以这个范围内的自动装箱(相当于调用valueOf(int i)方法)的数字都会从缓存中获取,返回同一个数字。

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值