介绍
工厂方法模式(Factory Method Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂方法模式中,定义一个用于创建对象的接口,让子类决定实例化哪一个类。
应用场景
(1)用户需要一个实例,关心创建的细节。
(2)用户需要一个类子类的实例,但不希望与该类的子类形成耦合。
模式结构
(1)抽象产品(Product):抽象类或接口,负责定义具体产品必须实现的方法。
(2)具体产品(ConcreteProduct):具体产品是一个类,Product的实现类或者子类。
(3)构造者(Creator):一个接口或抽象类。构造者负责定义一个称作工厂方法的抽象方法,该方法返回具体产品类的实例。
(4)具体构造者(ConcreteCreator):是Creator的子类或者实现类,具体构造者重写工厂方法使该方法返回具体产品的实例。
代码案例
例如,有一个笔芯类(PenCore),该类是一个抽象类。假设笔芯类有三个子类,分别是红笔芯类(RedPenCore)、蓝笔芯类(BluePenCore)、黑笔芯类(BlackPenCore),而系统设计的目的是为用户提供圆珠笔类(BallPen)的子类的实例,即含有笔芯的圆珠笔,也就是说系统想让用户使用圆珠笔类的子类的实例来得到笔芯类的子类的实例。
为此,在设计圆珠笔类的同时,决定让它依赖于笔芯类,并且提供了一个返回笔芯类对象的方法,比如:PenCore getPenCore(); 但是圆珠笔类本身并不知道用户需要哪种颜色的笔芯,即不知道用户需要笔芯类的哪个子类的实例,因此圆珠笔类将getPenCore()方法设置为抽象方法,并将自己设置为抽象类,要求其子类重写(覆盖)getPenCore()方法,并使用getPenCore()方法返回笔芯类的一个特定子类的实例。比如,当用户需要蓝笔芯类的实例时,就不需要使用new运行符和蓝笔芯类的构造方法来来创建对象,代替地使用蓝笔芯类创建一个对象,该对象调用getPenCore()方法就可以为用户获得一个蓝笔芯类的实例,用户可以让这个实例调用有关方法写出蓝色的字了。
首先,创建抽象产品类(Product):
public abstract class PenCore {
String color;
public abstract void writeWord(String s);
}
创建三个具体产品类:
public class RedPenCore extends PenCore{
RedPenCore(){
color = "红色";
}
@Override
public void writeWord(String s){
System.out.println("写出"+color+"的字:"+s);
}
}
public class BluePenCore extends PenCore{
BluePenCore(){
color = "蓝色";
}
@Override
public void writeWord(String s){
System.out.println("写出"+color+"的字:"+s);
}
}
public class BlackPenCore extends PenCore{
BlackPenCore(){
color = "黑色";
}
@Override
public void writeWord(String s){
System.out.println("写出"+color+"的字:"+s);
}
}
创建构建者类:
public abstract class BallPen {
BallPen(){
System.out.println("生产了一只装有"+getPenCore().color+"笔芯的圆珠笔");
}
//工厂方法
public abstract PenCore getPenCore();
}
创建三个具体构造者类:
public class RedBallPen extends BallPen{
@Override
public PenCore getPenCore(){
return new RedPenCore();
}
}
public class BlueBallPen extends BallPen{
@Override
public PenCore getPenCore(){
return new BluePenCore();
}
}
public class BlackBallPen extends BallPen{
@Override
public PenCore getPenCore(){
return new BlackPenCore();
}
}
测试类:
public class ApplicationTest {
public static void main(String args[]){
PenCore penCore;
BallPen ballPen = new BlueBallPen();
penCore = ballPen.getPenCore();
penCore.writeWord("您好,很高兴认识你");
System.out.println("------");
ballPen = new RedBallPen();
penCore = ballPen.getPenCore();
penCore.writeWord("How are you");
System.out.println("------");
ballPen = new BlackBallPen();
penCore = ballPen.getPenCore();
penCore.writeWord("nice to meet you");
}
}
优点
(1)使用工厂方法可以让用户的代码和某个特定类的子类的代码解耦。
(2)工厂方法使用用户不必知道它所使用的对象是怎样被创建的,只需知道该对象有哪些方法即可。
缺点
如果产品类过多,我们就要生成很多的工厂类。如果我们要实现多个产品接口,不同产品接口有对应的产品族。
什么是产品族呢?简单的理解就是,不同牌子产的车里面会有跑车类型,家庭类型,商用类型等的车,不同牌子的车的跑车类型的车可以组成一个产品族。对于这种情况我们可以采用抽象工厂模式。