简单的介绍一下简单工厂模式的概念:
简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式;通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类
从介绍我们就可以提炼出一些特点:
- 每一个实例具有共同的父类
- 一个特定的类来负责创建其它类的实例
现在我们通过工厂模式来实现一个例子:我们现在需要一个水果工厂
来获得?、?…等不同的水果
一、首先创建一个它们(?、?)共同的父类Fruit
- 水果的父类
Fruit.java
public abstract class Fruit {
abstract void get();
}
二、现在我们来创建?、?的具体实现类
- ?类实现
Apple.java
public class Apple extends Fruit {
/**
* 获得苹果
*/
@Override
public void get() {
System.out.println("采集?");
}
}
- ?类实现
Banana.java
public class Banana extends Fruit {
/**
* 获得香蕉
*/
@Override
public void get() {
System.out.println("采集?");
}
}
三、一般我们都是通过普通的new
来创建一个对象,如下图:
//创建苹果和香蕉的实例对象
Fruit apple = new Apple();
apple.get();
Fruit banana = new Banana();
banana.get();
四、现在我们就需要通过工厂模式来对这个对象的创来进行改造一下了
- 我们创建一个
FruitFactory.java
工厂类(一般使用工厂模式的类名都是***Factory.java)
public class FruitFactory {
/**
* 根据不同的类型创建不同的对象
*
* @param type
* @return
*/
public static Fruit getFruit(String type) {
switch (type) {
case "apple":
return new Apple();
case "banana":
return new Banana();
default:
System.out.println("找不到所匹配的对象!");
return null;
}
}
}
- 调用的地方就可以进行简化一下了
Fruit apple = FruitFactory.getFruit("apple");
Fruit banana = FruitFactory.getFruit("banana");
apple.get();
banana.get();
运行的结果:
采集?
采集?
五、这样我们就实现了一个简单的工厂了,可以生产?、?水果了;但是仔细看会发现一个问题:当我们要生产一个新的水果如:?、?、?等时…我们需要对这个工厂的getFruit()
函数进行改造,如下:
/**
* 根据不同的类型创建不同的对象
*
* @param type
* @return
*/
public static Fruit getFruit(String type) {
switch (type) {
case "apple":
return new Apple();
case "banana":
return new Banana();
//西瓜
case "watermelon":
return new Watermelon();
//菠萝
case "pineapple":
return new Pineapple();
case "peach":
//桃
return new Peach();
default:
System.out.println("找不到所匹配的对象!");
return null;
}
}
如果我们还需要继续追加其他的水果,那么就得不停的改造这个函数;那我们有没有什么方法可以在进一步简化这里,答案当然是有的了如下:
六、使用反射进一步简化工厂对对象的创建
FruitFactory.java
public class FruitFactory {
/**
* 使用反射
* 进一步简化工厂的创建
*
* @param type 这个参数就是需要创建的实例路径,eg:包名.类名
*/
public static Fruit getFruit2(String type) throws ClassNotFoundException,
IllegalAccessException, InstantiationException {
//加载类的实例
Class<?> name = Class.forName(type);
return (Fruit) name.newInstance();
}
}
那么同样的调用处的地方也需要跟着来一起变化
//使用反射创建
try {
Fruit apple = FruitFactory.getFruit2(Apple.class.getName());
apple.get();
Fruit banana = FruitFactory.getFruit2(Banana.class.getName());
banana.get();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
这里需要注意⚠️一下,type参数这里必须是要创建的对象的全路径例如:com.xx.xx.Apple
,否则会抛出ClassNotFoundException
七、 通过这种方式进行类的对象创建再遇到需要不断追加不同的对象时,就不在需要改造工厂方法了只需要再使用的地方传入对行的对象就行,如下:
Fruit watermelon = FruitFactory.getFruit2(Watermelon.class.getName());
Fruit pineapple = FruitFactory.getFruit2(Pineapple.class.getName());
Fruit peach = FruitFactory.getFruit2(Peach.class.getName());
//.....等等