工厂方法模式(Factory Method Pattern)又称为工厂模式。定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。
2.1 抽象产品(Product):
工厂方法模式所创建的对象的超类,也就是所有产品类的共同父类或共同拥有的接口。在实际的系统中,这个角色也常常使用抽象类实现。
2.2 具体产品(ConcreteProduct):
这个角色实现了抽象产品(Product)所声明的接口,工厂方法模式所创建的每一个对象都是某个具体产品的实例。
2.3 抽象工厂(Factory):
担任这个角色的是工厂方法模式的核心,任何在模式中创建对象的工厂类必须实现这个接口。在实际的系统中,这个角色也常常使用抽象类实现。
2.4 具体工厂(ConcreteFactory):
担任这个角色的是实现了抽象工厂接口的具体Java类。具体工厂角色含有与业务密切相关的逻辑,并且受到使用者的调用以创建具体产品对象。
实例模型:电视都有一个功能就是播放电视。电视的工厂负责生产电视,而三星的工厂负责生产三星牌子的电视,LG工厂负责生产LG电视。
抽象产品接口:
package zzw.cn.factory.method;
public interface ITv
{
void watchTv();
}
抽象工厂接口:
package zzw.cn.factory.method;
public interface ITvFactory
{
ITv createTv();
}
具体产品类:
LG电视产品类:
package zzw.cn.factory.method;
public class LGTv implements ITv
{
@Override
public void watchTv()
{
System.out.println("It is a LG TV !");
}
}
Samsung电视产品类:
package zzw.cn.factory.method;
public class SamsungTv implements ITv
{
@Override
public void watchTv()
{
System.out.println("It is a Samsung TV !");
}
}
具体的工厂类:
LG电视工厂类:
package zzw.cn.factory.method;
public class LGTVFactory implements ITvFactory
{
@Override
public ITv createTv()
{
return new LGTv();
}
}
Samsung电视工厂类:
package zzw.cn.factory.method;
public class SamsungTVFactory implements ITvFactory
{
@Override
public ITv createTv()
{
return new SamsungTv();
}
}
测试类:
package zzw.cn.factory.method;
public class MethodFactoryTest
{
public static void main(String[] args)
{
//创建LG电视的生产工厂
ITvFactory factoryLG = new LGTVFactory();
//生产LG电视
ITv tvLG = factoryLG.createTv();
//播放LG电视
tvLG.watchTv();
//创建三星电视的生产工厂
ITvFactory factorySamsung = new SamsungTVFactory();
//生产三星电视
ITv tvSamsung = factorySamsung.createTv();
//播放Samsung电视
tvSamsung.watchTv();
}
}
优点:
a.用户只需要关心产品对应的工厂,甚至无需关心创建细节或具体产品类的类名。
b. 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能自主决定如何创建哪种产品对象,而创建细节都封装在具体工厂内部。
c. 要添加新的产品时,无需修改抽象工厂和抽象产品提供的接口,无需修改客户端,也无需修改其他的具体工厂和具体产品,只要添加一个具体工厂和具体产品即可,从而提高系统的可扩展性(符合开闭原则)
缺点:
a. 在添加新产品时,要编写新的具体产品类,并要提供与之对应的具体工厂类。系统软件个数也成对增加,从而增加了系统的复杂度,带来更多开销.
b. 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度。