工厂方法模式也是工厂模式的一种。我们在简单工厂模式中了解到,在对产品进行拓展的时候,增加一个新的产品时,都需要对工厂类的代码进行修改,这样就打破了开闭原则,而工厂方法模式是在简单工厂模式上进行的改进,主要是将工厂类进行抽象化,把用于实例化特定产品类的代码转移到实现抽象方法的子类中去。
再以创建手机为例子,手机可能有多个牌子,这里就以华为和小米作为例子:
主要类有:
抽象产品类:Phone
具体产品类:Huawei 、Mi
抽象工厂类:PhoneFactory
具体工厂类:HuaweiPhoneFactory、MiPhoneFactory
跟简单工厂差不多,只不过多了一个抽象工厂类,把具体实例化的代码交给具体工厂类去实现
实现代码如下:
1、定义抽象产品类Phone,并定义一个返回手机牌子的方法,交给具体产品类去实现
package com.bran.factory.type2;
public interface Phone {
public String brand();
}
2、定义具体产品类Huawei、Mi,要实现抽象产品类Phone接口
package com.bran.factory.type2;
public class Huawei implements Phone{
@Override
public String brand() {
return "这是华为手机";
}
}
package com.bran.factory.type2;
public class Mi implements Phone{
@Override
public String brand() {
return "这是小米手机";
}
}
3、定义抽象工厂类PhoneFactory,定义一个用来实例化产品的抽象方法,交由不同的具体工厂类去实现该方法
package com.bran.factory.type2;
public abstract class PhoneFactory {
protected abstract Phone createPhone();
}
4、定义具体工厂类HuaweiPhoneFactory、MiPhoneFactory,实现抽象工厂类PhoneFactory的抽象方法,用于实例化产品;交由HuaweiPhoneFactory负责实例化Huawei产品,MiPhoneFactory负责实例化Mi产品。
package com.bran.factory.type2;
public class HuaweiPhoneFactory extends PhoneFactory{
@Override
protected Phone createPhone() {
return new Huawei();
}
}
package com.bran.factory.type2;
public class MiPhoneFactory extends PhoneFactory{
@Override
protected Phone createPhone() {
return new Mi();
}
}
5、测试工厂方法模式
package com.bran.factory.type2;
public class FactoryTest {
public static void main(String[] args) {
PhoneFactory huaweiPhoneFactory = new HuaweiPhoneFactory();
PhoneFactory miPhoneFactory = new MiPhoneFactory();
Phone huawei = huaweiPhoneFactory.createPhone();
Phone mi = miPhoneFactory.createPhone();
System.out.println(huawei.brand());
System.out.println(mi.brand());
}
}
6、当需要扩展产品时,假如又增加了一个Samsung的产品,只需要再定义一个具体产品类Samsung,和一个具体工厂类SamsungPhoneFactory就可以了,而不需要对原有的PhoneFactory的代码进行修改。
package com.bran.factory.type2;
public class Samsung implements Phone{
@Override
public String brand() {
return "这是三星手机";
}
}
package com.bran.factory.type2;
public class SamsungPhoneFactory extends PhoneFactory{
@Override
protected Phone createPhone() {
return new Samsung();
}
}
工厂方法模式虽然在简单工厂模式上进行改进了,但在运用起来还是有些弊端的,最主要的就是,每增加一个产品都需要增加一个对应产品的工厂类,产品如果多了的时候,会一定程度上增加了系统的复杂度,编译起来也会给系统带来额外的开销。