工厂方法模式(factory method pattern)从2方面认识。
编程技巧:这是对参数化工厂方法加以改进的经典技术,以多态来重构if-else、switch-case等分支结构。
设计思路:你一定要注意,工厂方法模式中Client关注的不是的产品(所以静态工厂中Door的例子,不适合),Client关注的是工厂!
1.以多态来重构分支结构
静态工厂的缺点是分支结构,需要增添新的分支时,程序不符合OCP。package creational.factory;在不使用配置文件和反射机制的情况下,
public class DoorFactory{
public static Door getObject(String typeName){//int ID
if(typeName.equals("D1")){
return new D1();
}else if(typeName.equals("D2")){
return new D2();
}else{
return null;
}
}
}
package creational.factory;
public class Hand{
static Door d = null;
public static void test(){
d = DoorFactory.getObject("D2");
d.m();
}
}
interface IDoorFactory {将工厂类泛化成抽象类型,以其子类多态地创建不同的产品如Door的子类。 它体现了一种非常重要的思考方式——以多态来重构if-else或switch-case结构。从重构分支结构的角度看,策略模式与[2.1.3工厂方法模式(3.3)]和[4.2状态模式(5.8)]是三胞胎。
public Door createDoor();
}
class D1Factory implements IDoorFactory {
public D1 createDoor() {
return new D1();
}
}//D2Factory 略
public class Client {
public static void main(String[] args) {
IDoorFactory factory = new D1Factory();
Door door= factory.createDoor();//生产D1
door.m();
}
}
2.颠倒黑白
上面例子中Hand采用工厂方法模式并不令人信服。Hand避免了依赖Door的具体子类D1、D2等,却变成了依赖具体的D1Factory、D2 Factory。通过依赖注入,可以使得Hand仅仅依赖Factory,但是,这样做不如直接通过依赖注入让Hand依赖抽象类型Door。
编程实践中,通常工厂是Client关注的主体,而工厂生产的产品被Client所忽视。例如Client开车ICar,不管什么车Client都可以开。现在,Car要找它的4S店/I4S,Client会关注各种4S店吗?interface ICar{ //工厂接口
public I4S get4S();//管你是那个4S店
public void move();
}
class BBCar implements ICar{
public I4S get4S() {
return new BB4S();
}
public void move(){
System.out.println("BBCar move");
}
}//QQCar 略
interface I4S{
void doSomething();
}//实现类略
public class Client{
public static void main(String[] args) {
ICar car =(ICar)tool.God.create("2-6-Car"); //ICar car =new BBCar();
car.move();
I4S repair = car.get4S();
repair.doSomething();
car.move();
}
}
由于受通用工具类如God——反射+配置的压制,现在应用程序中使用工厂方法模式比较少见。 在不使用配置文件的场合,如JDK的设计中广泛使用,典型例子:
public interface Iterable{
Iterator iterator();//返回一个迭代器
}