常见的创建型模式:
一、工厂模式的介绍
1.1、工厂模式的定义
在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。
1.2、工厂模式的分类
- 简单工厂模式:又称 静态工厂方法模式
- 工厂方法模式:又称 多态性工厂模式 或者 虚拟构造子模式
- 抽象工厂模式:又称 工具箱模式
1.3、为什么要用工厂模式 / 工厂模式的作用(好处)
(1)解耦:把对象的创建和使用分开来
(2)降低代码重复:如果创建某个对象的过程复杂,而且很多地方都要用到,就会有很多重复的代码
(3)降低维护成本:由于创建过程都由工厂统一管理,所以发生业务逻辑变化不需要找到所有需要创建对象的地方一个个修改,只需要在工厂里修改即可,降低了维护成本。
(4)最常用的实例化对象模式,用工场方法代替new操作的一种模式
二、简单工厂模式
相当于一个工厂中有各种产品创建在一个类中。客户无需知道具体产品的名称。只需要知道具体产品参数即可。但是类型多时不利于扩展,用的少。(只有一个工厂)
2.1、适用场景
- 需要创建的对象少;
- 客户端不关心对象的创建过程
2.2、角色分配
工厂角色:核心,负责实现创建所有实例的内部逻辑。工厂类可以直接被外界直接调用,创建所需的产品对象
抽象产品角色:简单工厂模式所创所有对象的父类,描述所有实例共有的公共接口
具体产品角色:创建目标。所有创建对象都是充当这个角色的某个具体类的实例
2.3、代码示例
public interface Car {//汽车厂(4S店)
public void run();
}
public class AoDi implements Car {//奥迪店
public void run() {
System.out.println("我是奥迪汽车..");
}
}
public class JiLi implements Car {//吉利店
public void run() {
System.out.println("我是吉利汽车...");
}
}
public class CarFactory {
public static Car createCar(String name) {
if (StringUtils.isEmpty(name)) {
return null;
}if(name.equals("奥迪")){
return new AoDi();
}
if(name.equals("吉利")){
return new JiLi();
}
return null;
}
}
//客户端
public class Client01 {
public static void main(String[] args) {
//只需要知道具体产品参数即可。只需要传一个参数
Car aodi =CarFactory.createCar("奥迪");
Car jili =CarFactory.createCar("吉利");
aodi.run();
jili.run();
}
}
三、工厂方法模式(用的多)
3.1、什么是工厂方法模式
又称多态性工厂模式。核心的工厂类不再负责所有的产品创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体子工厂类必须实现的接口,而不再接触哪一个产品类应当被实例化这种细节。
提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说 每个对象都有一个与之对应的工厂(有很多工厂)
3.2、适用场景
- 一个类不知道它所需要的对象的类:客户端不需要知道具体产品类的类名,要知道工厂类。只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;
- 一个类通过其子类来指定创建哪个对象:只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象;
- 将创建对象的任务委托给多个工厂子类中的某一个:客户端使用时无需关心是哪一个工厂子类创建产品子类,需要时再动态指定(可将具体工厂类的类名存储在配置文件或者数据库中)。
3.3、角色分配
抽象工厂角色:是工厂方法的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口
具体工厂角色:实现抽象工厂接口的 具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用已创建某种产品对象
抽象产品角色:产品对象的共同父类(或者 共同拥有的接口)
具体产品角色:实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应
3.4、工厂方法模式代码示例
public interface Car {
public void run();
}
public class AoDi implements Car {
public void run() {
System.out.println("我是奥迪汽车..");
}
}
public class JiLi implements Car {
public void run() {
System.out.println("我是吉利汽车...");
}
}
public class JiLiFactory implements CarFactory {//CarFactory 为上一个简单工厂的示例
public Car createCar() {
return new JiLi();
}
}
public class AoDiFactory implements CarFactory {
public Car createCar() {
return new AoDi();
}
}
public class Client {
public static void main(String[] args) {
Car aodi = new AoDiFactory().createCar();
Car jili = new JiLiFactory().createCar();
aodi.run();
jili.run();
}
}
四、抽象工厂模式
属于工厂方法模式的升级,不单单可以创建一种产品,而是可以创建一组产品。简单地说是工厂的工厂,抽象工厂可以创建具体工厂,由具体工厂来产生具体产品。
4.1、适用场景
- 和工厂方法一样,客户端不需要知道它所创建的对象的类
- 需要一组对象共同完成某种功能时,并且可能存在多种对象完成不同功能的情况(同属一个产品族的产品)
- 系统结构稳定,不会频繁增加对象
4.2、角色分配
- 抽象工厂角色:核心,与程序无关。任何在模式中创建的对象的工厂类必须实现这个接口
- 具体工厂类的角色:实现抽象工厂接口的具体工厂类,包含与应用程序相关的逻辑,并且受到应用程序调用以创建某一种产品对象
- 抽象产品角色:产品对象的父类(或者 共同拥有的接口)
- 具体产品角色:抽象工厂模式所创建的任何对对象都是某一个产品类的实例。在抽象工厂中创建的产品属于同一个产品族,这不同于工厂模式中的工厂只创建单一产品
4.3、抽象工厂的工厂与工厂方法中的工厂有什么区别?
抽象工厂是生产一整套有产品的(至少两个产品),这些产品必须是相互关系或者依赖的;而工厂方法中的工厂是生产单一产品的工厂。
4.4、抽象工厂Demo
假设现在存在AK、M4A1两类枪,每一种枪对应一种子弹。生产AK的工厂可以顺便生产AK使用的子弹,生产M4A1的工厂可以顺便生产M4A1使用的子弹
//1.创建相关接口:
public interface Gun {//枪
public void shooting();
}
public interface Bullet {//子弹
public void load();
}
//2.创建接口对应实现类:
public class AK implements Gun{//AK类 枪
@Override
public void shooting() {
System.out.println("shooting with AK");
}
}
public class M4A1 implements Gun {//M4A1类 枪
@Override
public void shooting() {
System.out.println("shooting with M4A1");
}
}
public class AK_Bullet implements Bullet {//AK子弹类
@Override
public void load() {
System.out.println("Load bullets with AK");
}
}
public class M4A1_Bullet implements Bullet {//M4A1子弹类
@Override
public void load() {
System.out.println("Load bullets with M4A1");
}
}
//3.创建工厂接口
public interface Factory {
public Gun produceGun();
public Bullet produceBullet();
}
//4.创建具体工厂
//生产AK和AK子弹的工厂
public class AK_Factory implements Factory{
@Override
public Gun produceGun() {
return new AK();
}
@Override
public Bullet produceBullet() {
return new AK_Bullet();
}
}
//生产M4A1和M4A1子弹的工厂
public class M4A1_Factory implements Factory{
@Override
public Gun produceGun() {
return new M4A1();
}
@Override
public Bullet produceBullet() {
return new M4A1_Bullet();
}
}
//5.测试
public class Test {
public static void main(String[] args) {
Factory factory;
Gun gun;
Bullet bullet;
factory =new AK_Factory();
bullet=factory.produceBullet();
bullet.load();
gun=factory.produceGun();
gun.shooting();
}
}
//输出结果:
Load bullets with AK
shooting with AK
五、简单工厂、工厂方法、抽象工厂之小结、区别
- 简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
- 工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
- 抽象工厂 :用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)