系列文章目录
文章目录
前言
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。实现了创建者和调用者分离,工厂模式分为简单工厂模式、工厂方法模式、抽象工厂模式
工厂模式的核心
- 将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦。
- 获取实例对象不用new,而是用工厂类创建对象
学习工厂模式的疑问
我们带着几个问题看工厂模式:
- 三个工厂模式之间有什么区别?
- 为什么要用工厂模式?或者工厂模式有什么好处?
工厂模式的三种模式:
简单工厂模式
简单工厂模式相当于是一个工厂中有各种产品,创建在一个类中,客户无需知道具体产品的名称,只需要知道产品类所对应的参数即可。但是工厂的职责过重,而且当类型过多时不利于系统的扩展维护
手机接口:
public interface Phone {
void call();
}
两个实现类:
public class IPhone implements Phone {
@Override
public void call() {
System.out.println("用苹果手机打电话");
}
}
public class MPhone implements Phone {
@Override
public void call() {
System.out.println("用小米手机打电话");
}
}
手机的工厂类:
public class PhoneFactory {
public Phone createShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("MPhone")){
return new MPhone();
} else if(shapeType.equalsIgnoreCase("IPhone")){
return new IPhone();
}
return null;
}
}
客户端:
public class Client {
public static void main(String[] args) {
PhoneFactory factory = new PhoneFactory();
Phone MPhone = factory.createShape("MPhone");
MPhone.call();
Phone IPhone = factory.createShape("IPhone");
IPhone.call();
}
}
单工厂的优点/缺点
- 优点:简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
- 缺点:很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则
工厂方法模式
工厂方法模式Factory Method,又称多态性工厂模式。在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节
手机工厂接口:
public interface PhoneFactory {
Phone createPhone();
}
两个子工厂:
public class MPhoneFactory implements PhoneFactory {
@Override
public Phone createPhone() {
return new MPhone();
}
}
public class IPhoneFactory implements PhoneFactory {
@Override
public Phone createPhone() {
return new IPhone();
}
}
客户端:
public class Client {
public static void main(String[] args) {
Phone MPhone = new MPhoneFactory().createPhone();
Phone IPhone = new IPhoneFactory().createPhone();
MPhone.call();
IPhone.call();
}
}
抽象工厂模式
上边的工厂方法模式是一种极端情况的抽象工厂模式(即只生产一种产品的抽象工厂模式),而抽象工厂模式可以看成是工厂方法模式的一种推广。
先理解产品族和产品等级
- 产品族:产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。一个品牌下面的所有产品;例如康师傅下面的绿茶,冰红茶,方便面 称为康师傅的产品族;小米下面的手机,ipad 称为小米的产品族;
- 产品等级:产品等级结构即产品的继承结构,如一个抽象类是绿茶,其子类有统一绿茶、康师傅绿茶,则抽象绿茶与具体品牌的绿茶之间构成了一个产品等级结构,抽象绿茶是父类,而具体品牌的绿茶是其子类。
实现抽象工厂模式
两个产品接口:
public interface Phone {
void call();
}
public interface IPad {
void play();
}
一个工厂接口:
public interface Factory {
Phone createPhone();
IPad createIPad();
}
四个产品实现类:
public class IPhone implements Phone {
@Override
public void call() {
System.out.println("用苹果手机打电话");
}
}
public class MPhone implements Phone {
@Override
public void call() {
System.out.println("用小米手机打电话");
}
}
public class IIPad implements IPad {
@Override
public void play() {
System.out.println("打开苹果ipad");
}
}
public class MIPad implements IPad {
@Override
public void play() {
System.out.println("打开小米ipad");
}
}
两个工厂实现类:
public class IFactory implements Factory{
@Override
public Phone createPhone() {
return new IPhone();
}
@Override
public IPad createIPad() {
return new IIPad();
}
}
public class MFactory implements Factory{
@Override
public Phone createPhone() {
return new MPhone();
}
@Override
public IPad createIPad() {
return new MIPad();
}
}
如果增加产品族或产品等级会怎么样?
增加产品等级
增加产品族
可见扩展产品族,只需要增加新的实现类即可,不需要修改原来的代码,符合设计模式中的OCP原则(开闭原则),也就是对扩展开放,对修改关闭
工厂模式区别
- 简单工厂 :用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
- 工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
- 抽象工厂 :用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)
为什么要用工厂模式,而不是直接new?
首先是为了解耦:把对象的创建和使用的过程分开。就是Class A 想调用 Class B ,那么A只是调用B的方法,而至于B的实例化,就交给工厂类。
其次工厂模式可以降低代码重复。如果创建对象B的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。我们可以这些创建对象B的代码放到工厂里统一管理。既减少了重复代码,也方便以后对B的创建过程的修改维护。
工厂模式适用的一些场景
- 对象的创建过程/实例化准备工作很复杂,需要初始化很多参数、查询数据库等。
- .类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。
Spring开发中的工厂设计模式
1.Spring IOC
- 看过Spring源码就知道,在Spring IOC容器创建bean的过程是使用了工厂设计模式
- Spring中无论是通过xml配置还是通过配置类还是注解进行创建bean,大部分都是通过简单工厂来进行创建的。
- 当容器拿到了beanName和class类型后,动态的通过反射创建具体的某个对象,最后将创建的对象放到Map中。
2.为什么Spring IOC要使用工厂设计模式创建Bean呢
- 在实际开发中,如果我们A对象调用B,B调用C,C调用D的话我们程序的耦合性就会变高。(耦合大致分为类与类之间的依赖,方法与方法之间的依赖。)
- 在很久以前的三层架构编程时,都是控制层调用业务层,业务层调用数据访问层时,都是是直接new对象,耦合性大大提升,代码重复量很高,对象满天飞
- 为了避免这种情况,Spring使用工厂模式编程,写一个工厂,由工厂创建Bean,以后我们如果要对象就直接管工厂要就可以,剩下的事情不归我们管了。Spring IOC容器的工厂中有个静态的Map集合,是为了让工厂符合单例设计模式,即每个对象只生产一次,生产出对象后就存入到Map集合中,保证了实例不会重复影响程序效率。