简单工厂
接口用来封装隔离具体的实现,目标是不让客户端知道封装体内部的具体实现。
简单工厂的位置位于封装体内,它和接口以及具体的实现在一起,算是封装体内部的一个类,所以简单工厂是知道具体实现的。
简单工厂封装对象的范围,建议控制在一个独立的组件级别或者一个模块级别,否则这个工厂会显得职责不明。
简单工厂命名建议:
- 类名建议为“模块名称+Factory”。比如,用户模块的工厂就称为:UserFactory。
- 方法名通常为“get+接口名称“或者是”create+接口名称“。比如有一个接口名称为UserEbi,那么方法名通常为getUserEbi或者是createUserEbi。
简单工厂方法的内部主要实现的功能是:选择合适的实现类来创建实例对象。选择的条件或者选择的参数通常来源有以下几种。
- 来源调用者
- 来源配置文件
- 来源运行时的某个值,比如从缓存中获取某个运行期的值
简单工厂的优点
- 帮助封装,让组件外部可以实现面向接口编程
- 解耦,实现调用者和具体实现类的解耦
简单工厂的缺点
- 可能增加客户端的复杂度:如果让调用者选择参数来实现具体的实现类,那么就必须让客户端能理解各个参数所代表的具体功能和含义,这样会增加客户端的使用难度,也不分暴露了内部的实现,这种情况可以选用可配置的方式来实现。
何时选择
- 需要封装隔离具体的实现,让外部只能通过接口来操作封装体,可以选择简单工厂,让客户端通过工厂来获取相应的接口,而不需要关心具体的实现。
- 如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂。
简单示范
the fllowing class diagram and code from : https://dragonprogrammer.com/design-patterns-java-simple-factory/
public interface Laptop {
void runTests();
}
public class NormalLaptop implements Laptop {
@Override
public void runTests() {
System.out.println("Running tests on a NormalLaptop...");
}
}
public class GamingLaptop implements Laptop {
@Override
public void runTests() {
System.out.println("Running tests on a GamingLaptop...");
}
}
public class LaptopFactory {
// Objects are created here
public Laptop createLaptop(String laptopType){
if (laptopType == null) {
return null;
}
switch (laptopType.toUpperCase()) {
case "NormalLaptop":
return new NormalLaptop();
break;
case "GamingLaptop":
return new GamingLaptop();
break;
default:
return null;
}
}
}
public class Client {
public static void main(String[] args) {
LaptopFactory laptopFactory = new LaptopFactory();
// Get object of type GamingLaptop and run tests.
Laptop myLaptop = laptopFactory.createLaptop("GamingLaptop");
myLaptop.runTests();
}
}