工厂模式
核心作用:实现创建者和调用者的分离
详细分类:
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
工厂模式满足的OOP原则:
- 开闭原则:一个软件的实体应当对扩展开放,对修改关闭
- 依赖倒转原则:要针对接口编程,不要针对实现编程
- 迪米特法则:只与你直接的朋友通信,而避免和陌生人通信
本质:实例化对象不使用new,用工厂方法代替
来一个简单的例子
创建一个汽车接口
public interface Car{
void name();
}
创建类
public class WuLin implements Car{
public void name(){
System.out.println("WuLin");
}
}
public class Tesla implements Car{
public void name(){
System.out.println("Tesla");
}
}
1. 简单工厂模式(静态工厂)
创建总工厂
/**
* 消费者只需要面对工厂,从工厂中调用静态方法返回,不需要自己new
* 但是每次新增车辆品种都需要修改工厂
*/
public class CarFactory{
// 方法一
public static Car getCar(String car){
if(car.equals("WuLin")){
return new WuLin();
}
if(car.equals("Tesla")){
return new Tesla();
}
return null;
}
// 方法二 比原来好一点,如果添加新车不用在原来方法的基础上修改逻辑
public static Car getWuLin(){
return new WuLin();
}
public static Car getTesla(){
return new Tesla();
}
}
2. 工厂方法模式
创建工厂接口
public interface CarFactory{
Car getCar();
}
创建Tesla工厂
public class TeslaFactory implements CarFactory{
public Car getCar(){
return new Tesla();
}
}
创建WuLin工厂
public class WuLinFactory implements CarFactory{
public Car getCar(){
return new WuLin();
}
}
从这可以看出工厂方法模式就是抽出总工厂接口
每个种类分别是创建自己的工厂实现工厂接口的方法(横向扩展)
每次新增一种车辆就创建一个自己的工厂实现接口
不用修改原来的代码, 符合开闭原则
但是每一次扩展都会多出一个扩展类(该类的工厂)
应用场景
- SpringIOC容器创建管理对象就是工厂模式(sqlSessionBeanFactory)
- 反射中Class对象的newInstance()方法
- JDBC中的Connection对象的获取
3. 抽象工厂模式
一个超级工厂,创建其他工厂的工厂
再来一个例子
创建两个产品
public interface Phone{
void startup();
void shutdown();
void callup();
void sendSMS();
}
public interface Router{
void startup();
void shutdown();
void setting();
}
创建两个公司类分别实现两个产品
// Phone
public class HuaweiPhone implements Phone{
public void startup(){
System.out.println("Huawei开机");
}
public void shutdown(){
System.out.println("Huawei关机");
}
public void callup(){
System.out.println("Huawei打电话");
}
public void sendSMS(){
System.out.println("Huawei发短信");
}
}
public class XiaomiPhone implements Phone{
public void startup(){
System.out.println("Xiaomi开机");
}
public void shutdown(){
System.out.println("Xiaomi关机");
}
public void callup(){
System.out.println("Xiaomi打电话");
}
public void sendSMS(){
System.out.println("Xiaomi发短信");
}
}
// Router
public class HuaweiRouter implements Router{
public void startup(){
System.out.println("Huawei开机");
}
public void shutdown(){
System.out.println("Huawei关机");
}
public void setting(){
System.out.println("Huawei设置");
}
}
public class XiaomiRouter implements Router{
public void startup(){
System.out.println("Xiaomi开机");
}
public void shutdown(){
System.out.println("Xiaomi关机");
}
public void setting(){
System.out.println("Xiaomi设置");
}
}
创建超级工厂
// 决定生产什么产品
public interface ProductFactory{
// 生产手机
Phone phoneProduct();
// 生产路由器
Roter routerProduct();
}
创建产品工厂(实现超级工厂)
// 具体实现
public class HuaweiFactory implements ProductFactory{
public Phone phoneProduct(){
return new HuaweiPhone();
}
public Router routerProduct(){
return new HuaweiRouter();
}
}
public class XiaomiFactory implements ProductFactory{
public Phone phoneProduct(){
return new XiaomiPhone();
}
public Router routerProduct(){
return new XiaomiRouter();
}
}
定义一个产品,这个产品有很多的品牌,
品牌都实现了这个产品需要的功能,
定义一个超级工厂,去创建这些品牌的工厂,
超级工厂有生产这些产品的抽象方法,交给不同品牌的工厂去生产各自品牌的产品
优点:
- 无需关心创建细节
- 将系列产品统一到一起创建
缺点:
- 扩展困难
- 增加抽象性和理解难度
超级工厂是管理多个产品线的工厂(不负责产品),而前两个模式是管理单个产品线
比如说多增加一个生产笔记本, 只需要在抽象工厂模式的超级工厂里增加抽象方法即可