工厂模式
我对工厂模式最初的理解
我在想如果是用interface来当做工厂的通用接口,那么具体的工厂子类如何通过字符串来确定需要自己来生产产品呢?如果是判断字符串是否和自己的类名相同,那为什么不写一个总的工厂方法来集中决定一个产品应该由哪个工厂子类来生产呢?
如果是由一个总工厂决定是由哪个子类来生产产品的,那么子工厂类的生产方法和总工厂类的生产方法就可以不同,具体来说总工厂的生产方法需要一个字符串来决定具体是哪个子类,但是子类却没有这个必要。
如果非要通过抽象接口来指定具体的子工厂类,而不设置总工厂类,那么具体的子工厂类的指派的任务就不得不交给语法机制本身来完成了,换句话说这个就已经不是模式的范围内了,而是要依赖于具体的语言语法了,这个就不符合设计模式是与具体的语言语法无关的特性了。所以如果想纯粹解释工厂模式就不能使用interface这个东西来指派子工厂类了。
那么可不可以使用抽象类呢?抽象类是不能被实例化的,但是它的方法是可以有实现的,而这个方法的实现的目的就是给子类的去调用的。为什么呢?因为抽象类无法被实例化,所以你就不能用抽象类的实例去调用位于抽象类内部的工厂方法了。
于是乎,你只能用一个实体类,这个实体类我姑且称之为总工厂类,与之相对应的就是子工厂类。
因为决定某种产品应该由哪个自工厂类去生产的逻辑是写在总工厂的工厂方法中的,所以自工厂类的生产方法和总工厂类的生产方法就不同了。具体来说就是子工厂类的生产方法只需要知道生产就行了,而总工厂类的工厂方法是负责制定让哪个子类的工厂方法来生产。于是就有了两个工厂方法,本来因为子工厂类和总工厂类都是工厂类,可以用interface来规定工厂类都有的方法的,但是我想只让子工厂类来实现子工厂的工厂方法,总工厂类实现总工厂的工厂方法,并且我只想写一个interface,但是interface规定必须要实现它的全部方法,这并不是我想要的。如果是用抽象类来做的话,上面已经说了是无法调用总工厂方法的。如果是在实体类里面放一个抽象子工厂生产方法让子工厂类去继承的话,那么实体类就必须变成抽象类了。想来想去我还是决定用两个interface,一个用来规定总工厂的工厂方法,另一个用来规定子工厂的工厂方法。那么由此看来子工厂和总工厂应该是两种不同的类型才对。
以上是我对工厂模式的理解。
这样做的缺陷
但是上述做法的确是存在缺陷的,因为灵活性不够,因为总工厂中可以被实例化的类型是写死在里面的,万一哪天需要根据需求来实现添加新类型的产品,你就要去改源代码,改源代码可不是类具有灵活性和可扩展性的表现啊!!!
使用
package com.company;
public class Main {
public static void main(String[] args) {
// write your code here
try {
Product one = new Factory().generalFactory(ProductA.class.toString());
one.printProducttionInformation();
Product two = new Factory().generalFactory(ProductB.class.toString());
two.printProducttionInformation();
Product three = new Factory().generalFactory(Product.class.toString());
three.printProducttionInformation();
} catch (NullPointerException e) {
System.out.println(e.toString());
}
}
}
输出
A产品
B产品
java.lang.NullPointerException: 该产品无法生产
Process finished with exit code 0
实现
产品接口
package com.company;
public interface Product {
/**
* 产品所具备的通用操作
*/
void printProducttionInformation();
}
A产品
package com.company;
public class ProductA implements Product {
@Override
public void printProducttionInformation() {
System.out.println("A产品");
}
}
B产品
package com.company;
public class ProductB implements Product {
@Override
public void printProducttionInformation() {
System.out.println("B产品");
}
}
总工厂接口
package com.company;
public interface HeadquartersFactory {
Product generalFactory(String className);
}
子工厂接口
package com.company;
public interface ProduceFactory {
Product productCreator();
}
总工厂
package com.company;
public class Factory implements HeadquartersFactory {
@Override
public Product generalFactory(String className) {
Product product = null;
if (className.equals(ProductA.class.toString())) {
product = new FactoryA().productCreator();
} else if (className.equals(ProductB.class.toString())) {
product = new FactoryB().productCreator();
} else {
throw new NullPointerException("该产品无法生产");
}
return product;
}
}
A工厂
package com.company;
public class FactoryA implements ProduceFactory {
@Override
public Product productCreator() {
return new ProductA();
}
}
B工厂
package com.company;
public class FactoryB implements ProduceFactory {
@Override
public Product productCreator() {
return new ProductB();
}
}