0 重要
0.1 核心
通常情况,创建对象考虑用静态工厂方法代替构造器
0.2 需要掌握的东西
0.2.1 静态工厂的缺点:
- 类如果不含公有的或者受保护的构造器,就不能被子类化
这个很好理解,如果类不含上述的这两种构造器,当然就没办法被继承。但实际这样或许也是一个好处,因为这样能鼓励程序员使用复合,而不是继承,这正是不可变类型所需要的。
参考:https://blog.csdn.net/weixin_42522009/article/details/114103361
- 程序员很难发现静态工厂方法
因为静态工厂方法是自定义的,它们没有像构造器那样被明确规定如何实例化,因此程序员往往很难查明如何通过静态工厂方法实例化一个类,因此我们便需要遵守一些静态工厂方法的惯用名称。
解决该问题的方法见0.2.2
0.2.2 如何区分静态工厂方法和其他静态方法
通过方法名区分,使用约定熟成的静态方法名:
类型转换:from,valueOf,of
获取或创建该类:getInstance,newInstance,getType(参考2.3),newType,type,create等
详细的可以参考这篇
https://blog.csdn.net/a517865058/article/details/104829478
1 内容
1.0 静态工厂方法定义
Fragment fragment = new MyFragment(); // or Date date = new Date(); 然而实际中是这样: Fragment fragment = MyFragment.newIntance(); // or Calendar calendar = Calendar.getInstance(); // or Integer number = Integer.valueOf("3"); 像上面这样的:不通过 new,而是用一个静态方法来对外提供自身实例的方法,即为我们所说的静态工厂方法。
参考:https://blog.csdn.net/weixin_44148815/article/details/87653744
1.1 静态工厂方法与构造器相比的优点
- 静态工厂方法有名称,便于阅读
如BigInteger的判断质数的方法,通过名称可能为质数,方便理解
public static BigInteger probablePrime(int var0, Random var1) { if (var0 < 2) { throw new ArithmeticException("bitLength < 2"); } else { return var0 < 95 ? smallPrime(var0, 100, var1) : largePrime(var0, 100, var1); } }
- 不必再每次调用它们的时候都创建一个新的对象,节省了开销
- 静态工厂方法可以返回原类型的任何子类型的对象
如下:java.util.Collections 有如下方法
public static <T> ArrayList<T> list(Enumeration<T> var0) { ArrayList var1 = new ArrayList(); while(var0.hasMoreElements()) { var1.add(var0.nextElement()); } return var1; } public static <T> Set<T> unmodifiableSet(Set<? extends T> var0) { return new Collections.UnmodifiableSet(var0); }
上边代码直接从源码拿到,最好参考右侧网址,便于理解:https://blog.csdn.net/u014519120/article/details/78741481
- 创建参数化类型实例时,代码更加简洁(参考泛型的使用)
1.2 静态工厂方法与构造器相比的缺点
见0.2.1
2 代码演练
2.1 静态工厂方法demo
静态工厂类:
package com.ddwei.test.core.chapter1; public class CreateObject { /*** * 静态工厂方法 * @author weidoudou * @date 2022/4/11 7:25 * @param b 请添加参数描述 * @return java.lang.Boolean **/ public static Boolean valueOf(boolean b){ return b ? Boolean.TRUE : Boolean.FALSE; } }
测试类:
package com.ddwei.test.core.chapter1; import com.alibaba.fastjson.JSON; public class CreateObjectTest { public static void main(String[] args) { Boolean b = CreateObject.valueOf(true); System.out.println(JSON.toJSONString(b.hashCode())); } }
日志:
1231
Process finished with exit code 0
2.2 不含公有或受保护的构造器,不能被子类化demo
父类:
package com.ddwei.test.core.chapter1.demo12; public class FatherDemo { private int age; private FatherDemo(){ } }
子类:
2.3 getType的使用demo1
静态工厂1
package com.ddwei.test.core.chapter1.demo13; public class SpringFactory { /** *蝴蝶春天有翅膀 * @author weidoudou * @date 2022/4/12 7:09 * @param * @return com.ddwei.test.core.chapter1.demo13.ButterFly **/ public static ButterFly getButterFly(){ ButterFly butterFly = new ButterFly(); butterFly.setHaveWing(true); return butterFly; } }
静态工厂2
package com.ddwei.test.core.chapter1.demo13; public class WinterFactory { /** * 蝴蝶冬天无翅膀 * @author weidoudou * @date 2022/4/12 7:09 * @param * @return com.ddwei.test.core.chapter1.demo13.ButterFly **/ public static ButterFly getButterFly(){ ButterFly butterFly = new ButterFly(); butterFly.setHaveWing(false); return butterFly; } }
实体类:
package com.ddwei.test.core.chapter1.demo13; import lombok.Setter; @Setter public class ButterFly { /** * 是否有翅膀 */ private boolean haveWing; }
2.4 getType的使用demo2
package com.ddwei.test.core.chapter1.demo13; import java.io.IOException; import java.nio.file.FileStore; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class StaticDemo { public static void main(String[] args) throws IOException { Path path = Paths.get("D:/wdd"); FileStore fs= Files.getFileStore(path); } }