1.工厂方法模式的定义
定义一个用于创建对象的接口,由子类决定具体实例化哪个类。FactoryMethod模式将类的实例化延迟到子类实现。
2.工厂方法模式的使用场景
当A对象需要调用B对象的方法时,可以使用new关键字来创建一个B实例,然后调用B实例的方法,这种做法的坏处在于:A类的方法直接调用了B类的类名(这种方式也被称为硬编码耦合),一旦系统需要重构:需要使用C类来代替B类时,程序不得不改写A类代码。如果应用中有100个或10000个类以硬编码方式耦合了B类,则需要重写100个、10000个地方…这显然是一种非常可怕的事情。
换一个角度来看这个问题:对于A对象而言,它只需要调用B对象的方法,并不是关心B对象实现、创建过程。考虑让B类实现一个IB接口,而A类只需要IB接口耦合——A类并不直接使用new关键字来创建B实例,二是重新定义一个工厂类:IBFactory,由该工厂类来负责创建IB实例:而A类通过调用IBFactory工厂方法来得到IB的实例。
如果系统需要重构:需要使用C类代替B类,只需要让C类也实现IB接口,并改写IBFactory工厂中创建IB实例的实现代码,让该工厂生产C(实现了IB接口)实例即可,由于所有依赖IB实例的对象都是通过工厂来获取IB实例的,所以它们都将改为获得C实例,这就完成了系统重构。这种将多个类对象交给工厂类来生成的设计方式被称为工厂方法模式。
3.工厂方法模式的UML类图
4.工厂方法模式的实现
//工厂类,用于创建具体对象
public class OutputFactory{
public Output createOutput(){
//改行代码用于控制系统到底使用Output哪个实现类
return new Printer();
}
}
//抽象产品类,由具体产品类实现
public interface Output{
void out();
void getData();
}
//具体产品类,实现抽象类方法
public class Printer implements Output{
private String data;
public void out(){
System.out.println("打印机打印:"+data);
}
public void getData(String data){
this.data=data;
}
}
//客户端类
public class Computer{
private Output out;
public Computer(Output out){
this.out = out;
}
//定义一个模拟打印的方法
public void print(){
out.out();
}
//定义一个模拟获取字符串输入方法
public void keyIn(String data){
out.getData(data);
}
public static void main(String[] args){
//创建OutputFactory
OutputFactory of = new OutputFactory();
//创建Output对象
Output out = of.createOutput();
//将Output对象传入,创建Computer对象
Computer c = new Computer(out);
c.keyIn("测试数据1");
c.print();
}
}
5.总结
总的来说,工厂方法模式是一个很好的设计模式,但存在缺点也是在所难免,每次我们为工厂方法模式添加新的产品时就要编写一个新的产品类,同时还要引入抽象层,这必然会导致类结构的复杂化,所以,在某些情况比较简单时,是否要使用工厂方法模式,需要设计者权衡利弊了。