工厂三兄弟设计模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_28196435/article/details/86739903

工厂模式

工厂模式一般是负责创建对象的设计过程,在设计中可以分为三个子设计模式

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

简单工厂模式

简单工厂用的比较多,如果不使用简单工厂的话,客户端的依赖往往会比较多,
比如创建汽车对象,可能会创建很多的汽车,UML图如下
不使用简单工厂的客户端UML类图
这里可以使用简单工厂来简化创建对象步骤,减少客户端对类的依赖,降低耦合。
我们新建一个CarFactory类来创建不同的Car。

public class CarFactory {
    public static Car createAudi(){
        return new Audi();
    }
    
    public static Car createBMW(){
        return new BMW();
    }
}

简单工厂的UML类图
这样客户端就减少了对类的依赖,并且如果后期还有新的Car,添加也是很方便的
再举一个用javascript的简单工厂例子

/** 
 * function: 工厂模式
 * 场景: $('div') React.createElement vue异步组件
 */

class Product{
    constructor(name) {
        this.name = name
    }

    init(){
      console.log('init')
    }

    fun1(){
      console.log('fun1')
    }

    fun2(){
        console.log('fun2')
    }
}

class Creator {
    static create(name){
        return new Product(name)
    }
}

const p = Creator.create('p1')
p.init()
p.fun1()
p.fun2()

还有一个基于vue音乐应用的创建音乐对象的例子,用的也是简单工厂模式

import { getLyric, getSongsUrl } from 'api/song'
import { ERR_OK } from 'api/config'
import { Base64 } from 'js-base64'

export default class Song {
  constructor ({ id, mid, singer, name, album, duration, image, url }) {
    this.id = id
    this.mid = mid
    this.singer = singer
    this.name = name
    this.album = album
    this.duration = duration
    this.image = image
    this.filename = `C400${this.mid}.m4a`
    this.url = url
  }

  getLyric () {
    if (this.lyric) {
      return Promise.resolve(this.lyric)
    }
    return new Promise((resolve, reject) => {
      getLyric(this.mid).then((res) => {
        if (res.retcode === ERR_OK) {
          this.lyric = Base64.decode(res.lyric)
          resolve(this.lyric)
        } else {
          reject(new Error('no lyric'))
        }
      })
    })
  }
}

export function createSong (musicData) {
  return new Song({
    id: musicData.songid,
    mid: musicData.songmid,
    singer: filterSinger(musicData.singer),
    name: musicData.songname,
    album: musicData.albumname,
    duration: musicData.interval,
    image: `https://y.gtimg.cn/music/photo_new/T002R300x300M000${musicData.albummid}.jpg?max_age=2592000`,
    url: musicData.url
  })
}

简单工厂模式在封装处理数据中还是能发挥很多作用的。
javascript一般使用的是简单工厂模式,抽象工厂和工厂方法用的比较少。

总结

简单工厂模式使用场景很多,但是在做大型架构的时候,不符合开放封闭原则,当需要新增类的时候,必须去修改工厂方法。


工厂方法模式

工厂方法模式,即实现的功能和简单工厂是一样的,但是符合开放封闭原则
首先需要设计和定义工厂要实现的接口,这个接口的作用一般用来创建对象的
然后定义每一个具体类的工厂,并分别实现。

package com.natsuki;

/**
 * @Date: 2019-02-01
 * @Description: 工厂方法的接口
 */
public interface ICarFactory {
    Car createCar();
}

package com.natsuki;

/**
 * @Date: 2019-02-01
 * @Description:
 */
public class AudiFactory implements ICarFactory {

    @Override
    public Car createCar() {
        return new Audi();
    }

}

package com.natsuki;

/**
 * @Date: 2019-02-01
 * @Description:
 */
public class BMWFactory implements ICarFactory {

    @Override
    public Car createCar() {
        return new BMW();
    }
}

总结

工厂方法是简单工厂的进一步抽象,符合开闭原则,但是缺点也比较明显,类的数量明显增多
所以到底使用简单工厂还是工厂方法,需要具体情况具体分析


抽象工厂模式

简单工厂和工厂方法只能生产同一类的产品,但是如果现在不仅仅需要生产汽车,还需要同时生产发动机,轮胎,那就是生产不同类的产品了,这有一个专业术语叫产品族。
抽象工厂创建的是不同类的产品,他们是一起增加的,是一个整体。
比如有发动机接口和其实现类

package com.natsuki;

/**
 * @Date: 2019-02-01
 * @Description: 不同的产品
 */
public interface Engine {
    void run();
    void start();
}

class LuxuryEngine implements Engine{

    @Override
    public void run() {
        System.out.println("12缸发动机");
    }

    @Override
    public void start() {
        System.out.println("100米4秒");
    }
}

class LowEngine implements Engine {

    @Override
    public void run() {
        System.out.println("4缸发动机");
    }

    @Override
    public void start() {
        System.out.println("100米7秒");
    }
}

座椅接口及其实现类

package com.natsuki;

/**
 * @Date: 2019-02-01
 * @Description:
 */
public interface Seat {
    void massage();
}

class LuxurySeat implements Seat {

    @Override
    public void massage() {
        System.out.println("自动调节");
    }
}

class LowSeat implements Seat {

    @Override
    public void massage() {
        System.out.println("不能自动调节");
    }
}

这样就有两个不同的产品类,然后我们需要进行组合,创建,形成一个整体,这时候抽象工厂设计模式就用上了

首先创建一个通用的抽象工厂接口

package com.natsuki;

/**
 * @Date: 2019-02-01
 * @Description: 抽象工厂的接口
 */
public interface ICarFactory {
    Engine createEngine();
    Seat createSeat();
}

创建具体的抽象工厂

public class LuxuryCarFactory implements ICarFactory {
    @Override
    public Engine createEngine() {
        return new LuxuryEngine();
    }

    @Override
    public Seat createSeat() {
        return new LuxurySeat();
    }
}
public class LowCarFactory implements ICarFactory {
    @Override
    public Engine createEngine() {
        return new LowEngine();
    }

    @Override
    public Seat createSeat() {
        return new LowSeat();
    }
}

总结

抽象工厂适合产品族的创建,我们通过例子能够发现,抽象工厂只能实现一族产品的创建,而不能增加单一产品。增加单一产品可以使用简单工厂模式和工厂方法模式

猜你喜欢

转载自blog.csdn.net/baidu_28196435/article/details/86739903