工厂模式
工厂模式一般是负责创建对象的设计过程,在设计中可以分为三个子设计模式
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
简单工厂模式
简单工厂用的比较多,如果不使用简单工厂的话,客户端的依赖往往会比较多,
比如创建汽车对象,可能会创建很多的汽车,UML图如下
这里可以使用简单工厂来简化创建对象步骤,减少客户端对类的依赖,降低耦合。
我们新建一个CarFactory类来创建不同的Car。
public class CarFactory {
public static Car createAudi(){
return new Audi();
}
public static Car createBMW(){
return new BMW();
}
}
这样客户端就减少了对类的依赖,并且如果后期还有新的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();
}
}
总结
抽象工厂适合产品族的创建,我们通过例子能够发现,抽象工厂只能实现一族产品的创建,而不能增加单一产品。增加单一产品可以使用简单工厂模式和工厂方法模式