定义:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。
类型:创建型
适用场景:创建对象需要大量重复的代码;客户端(应用层)不依赖于产品类实例被如何创建、实现等细节;一个类通过其子类来指定创建哪个对象;客户端只需要知道创建某个类所需要的工厂即可。
优点:用户只需要关心所需产品相应的工厂,无需关心创建的细节;加入新的产品符合开闭原则,提高扩展性。
缺点:类的个数容易过多,增加复杂度;增加了系统的抽象性和理解难度。
案例
public abstract class Video { public abstract void produce(); }
public abstract class VideoFactory { public abstract Video getVideo(); }
public class FEVideoFactory extends VideoFactory{ @Override public Video getVideo() { return new FEVideo(); } }
public class FEVideo extends Video{ @Override public void produce() { System.out.println("录制FE课程视频"); } }
public class JavaVideoFactory extends VideoFactory { @Override public Video getVideo() { return new JavaVideo(); } }
public class JavaVideo extends Video { @Override public void produce() { System.out.println("录制Java课程视频"); } }
public class Test { public static void main(String[] args) { VideoFactory videoFactory2 = new JavaVideoFactory(); VideoFactory videoFactory3 = new FEVideoFactory(); Video video = videoFactory2.getVideo(); video.produce(); } }
上述代码中,首先定义了产品和产品工厂的抽象,在具体的工厂实例子类中,完成对具体产品的创建,满足开闭原则。
那比如我们后续还想要python的视频,只需要新增python的工厂和python的产品实现。
public class PythonVideoFactory extends VideoFactory { @Override public Video getVideo() { return new PythonVideo(); } }
public class PythonVideo extends Video { @Override public void produce() { System.out.println("录制Python课程视频"); } }
工厂方法是为了解决同一产品等级的业务抽象问题,比如上述代码中,前端视频和java视频都是视频,他们就属于同一产品等级。与产品等级对应的一个概念产品族,打个比方,海尔和美的,他们各自都能生产很多产品,如冰箱、空调、洗衣机等,那海尔和美的就是两个产品族,抽象工厂是用来解决产品族的抽象的问题的。理解好产品等级和产品族的概念对于区分工厂方法和抽象工厂的区别非常重要。
源码
JDK中的Collection获取iterator就交给了子类进行具体实现,随便找一个Collection的实现类Arraylist,在arraylist中获取iterator,返回了实现iterator接口内部类。
上述代码中,Collection就相当于工厂的抽象,iterator就是产品的抽象,Arraylist就是具体的工厂,Arraylist中的内部类Itr就是具体的产品。