更多关于设计模式的文章请点击:设计模式之禅(0)-目录页
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一、简单工厂模式
1.1、单一new方式
我们在开发项目时如果需要获取对象,通常会使用单一new的方式去获取它:
Object object1 = new Object1();
Object object2 = new Object2();
Object object3 = new Object3();
我们或许还会在创建出来后进行一些处理:
Object object1 = new Object1();
object1.setA(A);
object1.setB(B);
Object object2 = new Object2();
object2.setA(A);
object2.setB(B);
Object object3 = new Object3();
object3.setA(A);
object3.setB(B);
这会暴露出一个问题:
所有的创建过程和固定的操作都需要写出来,并且在本地代码中将其暴露。这不符合写入不变的、封装变化的代码的设计模式,所以说,我们需要一个类似于工厂的角色去产生这些对象,并且对它们进行一些固定的操作。这样就自然而然地引出了简单工厂模式(Simple Factory Pattern
)。
1.2、简单工厂模式
简单工厂模式(Simple Factory Pattern
)的使用很简单,再拿我们的动物简单工厂来举例子:
public class SimpleAnimalFactory{
public Animal getAnimal(String type){
if(type.equals("Dog")){
Animal dog = new Dog();
//处理dog
return dog ;
}else if(type.equals("Cat")){
Animal cat= new Cat();
//处理cat
return cat;
}
}
}
当我们需要Dog时,只需要创建SimpleAnimalFactory,再用其调用getAnimal(“Dog”)即可获得一只"经过处理的狗",而且这些创建和处理对"调用者"来说是"不可见"的,调用者并不在乎工厂内部到底做了什么,只需要获得经过处理的对象。
那么,工厂模式就这样讲完了吗?当然不是。其实,简单工厂模式并不算是一种设计模式,工厂模式也远没那么简单。
二、抽象工厂及工厂方法
2.1、将简单工厂改造成抽象工厂
在上面的简单工厂中,我们所实现的SimpleAnimalFactory已经能帮助我们获得简单的动物了,但是当我们需要动物园的动物时,我们需要制造一个ZooAnimalFactory;同理,当我们需要野生动物时,我们需要WildAnimalFactory,我们可以这样写:
- ZooAnimalFactory
public class ZooAnimalFactory{
public Animal getAnimal(String type) {
if(type.equals("ZooDog")){
return new ZooDog();
}else if(type.equals("ZooCat")){
return new ZooCat();
}
return null;
}
}
- WildAnimalFactory
public class WildAnimalFactory{
public Animal getAnimal(String type) {
if(type.equals("WildDog")){
return new WildDog();
}else if(type.equals("WildCat")){
return new WildCat();
}
return null;
}
}
如果你需要其他各种各样的工厂,我们只能一遍又一遍地写着,那么为什么我们不能抽取出来一个动物工厂超类,让其他工厂去继承它,获得工厂所需的方法和属性呢?这就是抽象工厂:
- AnimalFactory
public abstract class AnimalFactory {
public abstract Animal getAnimal(String type);
}
}
此时,我们的ZooAnimalFactory和WildAnimalFactory可以这样写:
- ZooAnimalFactory
public class ZooAnimalFactory extends AnimalFactory{
@Override
public Animal getAnimal(String type) {
if(type.equals("ZooDog")){
return new ZooDog();
}else if(type.equals("ZooCat")){
return new ZooCat();
}
return null;
}
}
- WildAnimalFactory
public class WildAnimalFactory extends AnimalFactory{
@Override
public Animal getAnimal(String type) {
if(type.equals("WildDog")){
return new WildDog();
}else if(type.equals("WildCat")){
return new WildCat();
}
return null;
}
}
2.2、为抽象工厂中添加工厂方法
我们上面的抽象工厂已经可以满足基本的需求了,但是还有一点美中不足:工厂中的动物由getAnimal(String type)方法创建,这里头真正产生动物的代码没有被封装起来,这就是所谓的工厂方法,即真正产生出对象的方法,我们可以在抽象工厂中添加一个工厂方法createAnimal(String type)
,并且让子类去重写这个工厂方法。
- AnimalFactory
/**
* @Auther: ARong
* @Date: 2018/11/25 19:34
* @Description: 动物工厂超类
*/
public abstract class AnimalFactory {
public Animal getAnimal(String type){
//调用createAnimal方法,该方法由实现类去重写
Animal animal = createAnimal(type);
return animal;
}
protected abstract Animal createAnimal(String type);
}
三、工厂模式总结
以上工厂模式的类,可以用简单的UML关系图来表示:
- AnimalFactory
/**
* @Auther: ARong
* @Date: 2018/11/25 19:34
* @Description: 动物工厂超类
*/
public abstract class AnimalFactory {
public Animal getAnimal(String type){
//调用createAnimal方法,该方法由实现类去重写
Animal animal = createAnimal(type);
return animal;
}
protected abstract Animal createAnimal(String type);
}
- ZooAnimalFactory
/**
* @Auther: ARong
* @Date: 2018/11/25 19:36
* @Description: AnimalFactory的实现类
*/
public class ZooAnimalFactory extends AnimalFactory{
//按需重写createAnimal方法
@Override
protected Animal createAnimal(String type) {
if(type.equals("ZooDog")){
return new ZooDog();
}else if(type.equals("ZooCat")){
return new ZooCat();
}
return null;
}
}
- WildAnimalFactory
/**
* @Auther: ARong
* @Date: 2018/11/25 19:41
* @Description: AnimalFactory的实现类,野生动物工厂
*/
public class WildAnimalFactory extends AnimalFactory{
@Override
protected Animal createAnimal(String type) {
if(type.equals("WildDog")){
return new WildDog();
}else if(type.equals("WildCat")){
return new WildCat();
}
return null;
}
}
- Animal
/**
* @Auther: ARong
* @Date: 2018/11/17 11:08
* @Description:动物的抽象类,定义动物的属性以及抽象行为和具体行为
*/
public abstract class Animal {
//动物名称
private String name;
//定义run方法
public abstract void run();
//get、set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
-
ZooCat/ZooDog/WildCat/WildDog的代码不列出了
-
测试
/**
* @Auther: ARong
* @Date: 2018/11/25 19:44
* @Description: 动物工厂测试
*/
public class TestAnimalFactory {
@Test
public void getZooAnimal(){
AnimalFactory zooAnimalFactory = new ZooAnimalFactory();
Animal zooDog = zooAnimalFactory.getAnimal("ZooDog");
zooDog.run();
}
@Test
public void getWildAnimal(){
AnimalFactory wildAnimalFactory = new WildAnimalFactory();
Animal wildCat = wildAnimalFactory.getAnimal("WildCat");
wildCat.run();
}
}