工厂模式
简介
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用共同的接口来指向新创建的对象。这样调用者只知道工厂方法,而不知道具体的对象。屏蔽产品的具体实现,调用者只关心产品的接口。
使用场景
当您准备使用new创建一个对象的时候,可以先考虑下改对象是否是某个接口或抽象类的实现或子类,该接口或抽象类是否还存在多其他实现或子类。如果是这样那你就可以考虑使用工厂模式将所有的实现或子类集中起来,这样便于管理,并且对于后期的扩展和维护都很方面。
类图
实现方式
工厂模式有多种实现方式,下面将为大家对比普通逻辑判断、反射、多静态方法模式的工厂方法的好处,通过对比推荐大家使用最好的方式。
公用代码
package com.rabbit.pattern.signfactory;
/**
* 所有动物的接口
* Created by HASEE on 2018/2/7.
*/
public interface Animal {
void eat();//吃
void say();//叫
}
package com.rabbit.pattern.signfactory;
/**
* 动物类:猫
* Created by HASEE on 2018/2/7.
*/
public class Cat implements Animal {
@Override
public void eat() {
System.out.printf("我是猫,我吃鱼");
}
@Override
public void say() {
System.out.printf("我是猫,喵喵喵");
}
}
package com.rabbit.pattern.signfactory;
/**
* 动物类狗
* Created by HASEE on 2018/2/7.
*/
public class Dog implements Animal {
@Override
public void eat() {
System.out.printf("我是狗,我吃骨头");
}
@Override
public void say() {
System.out.printf("我是狗,汪汪汪");
}
}
普通逻辑判断
package com.rabbit.pattern.signfactory;
/**
* Created by HASEE on 2018/2/7.
*/
public class CommonAnimalFactory {
public static final String DOG = "DOG";
public static final String CAT = "CAT";
public static Animal newInstance(String type) {
switch (type) {
case DOG : {
return new Dog();
}
case CAT : {
return new Cat();
}
default : {
throw new RuntimeException("找不到对应类型的动物");
}
}
}
}
普通逻辑判断方式实现的工厂类,虽然没什么大问题,但是如果我们添加多一个牛的类,那么工厂类的newInstance方法又还要新增一个case分支来判断类型。这样的做法就违背了“开闭原则”,Java的开闭原则要求对于扩展要开放,对于修改要封闭。所有违背了封闭原则。
反射
package com.rabbit.pattern.signfactory;
/**
* Created by HASEE on 2018/2/7.
*/
public class ReflectFactory {
public static Animal newInstatnce(Class<? extends Animal> clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
Animal animal = newInstatnce(Cat.class);
animal.eat();
animal.say();
}
}
反射方式避开了“开闭原则”,因为是通过反射方式创建对象,那么无论扩展了多少的子类都不用修改工厂类,只需要在初始化某个对象的时候将对象传递即可。但是这样调用者就必须知道需要实例化的是那个类才可以。这样无意间就暴露了实现,而且反射过程中需要耗费的资源可能比new方法构造还需要内存。
多静态方法
package com.rabbit.pattern.signfactory;
/**
* Created by HASEE on 2018/2/7.
*/
public class AnimalFactory {
public static Animal newDogInstance() {
return new Dog();
}
public static Animal newCatInstance() {
return new Cat();
}
}
多静态方法形式的工厂模式,对于普通逻辑判断方式避开了每次都需要添加一个分支来判断的弊端,代码更简介易懂。对于反射方式避开了因为反射而耗费的内存,但是无法躲避的是如果另外实现了类,那么就需要添加多一个方法。在Java类库中也有工厂类使用了该中模式,详情请看Executors类。整体来说多静态方法的方式是比普通逻辑判断和反射方式要好,虽然违背了“开闭原则”。
对于工厂模式如何做到不违背“开闭原则”,由于这个问题衍射出了“工厂方法模式”和“抽象工厂模式”两大设计模式,完美的解决了“开闭原则”的问题。这两种设计模式将在后面的博客中整理发出来。