工厂模式包括:简单工厂模式,工厂方法模式,抽象工厂模式
简单工厂模式
工厂方法根据参数直接创建实例:工厂->产品
一个人开了个咖啡馆,卖2种咖啡:美式咖啡、拿铁。
class AmericanoCoffee {
constructor() {
console.log('AmericanoCoffee');
}
}
class LatteCoffee{
constructor() {
console.log('LatteCoffee');
}
}
function createCoffeeFactory(name: string) {
switch (name) {
case 'AmericanoCoffee':
return new AmericanoCoffee();
case 'LatteCoffee':
return new LatteCoffee();
default:
return new Error('本店不支持');
}
}
// 简单工厂:工厂方法直接创建实例
createCoffeeFactory('AmericanoCoffee');
createCoffeeFactory('LatteCoffee');
代码非常简单,但是如果新增一样咖啡时,要扩展一个咖啡种类Cuppuccino,同时createCoffeeFactory的switch里面要新增一个case。
违法开闭原则:对扩展开发,对修改关闭。什么是扩展,什么是修改?
// 新增一个类CuppuccinoCoffee,就是扩展
class CuppuccinoCoffee{
constructor() {
console.log('LatteCoffee');
}
}
function createCoffeeFactory(name: string) {
switch (name) {
case 'AmericanoCoffee':
return new AmericanoCoffee();
case 'LatteCoffee':
return new LatteCoffee();
case 'CuppuccinoCoffee': // 修改了原有的代码,就是修改
return new CuppuccinoCoffee()
default:
return new Error('本店不支持');
}
}
createCoffeeFactory('CuppuccinoCoffee');
工厂方法模式
抽象一个工厂方法,具体的工厂创建产品
抽象工厂->具体工厂->一种产品
class AmericanoCoffee {
constructor() {
console.log('AmericanoCoffee');
}
}
class LatteCoffee{
constructor() {
console.log('LatteCoffee');
}
}
// 抽象工厂
abstract class CoffeeFactory {
abstract createCoffee();
}
// 具体工厂
class AmericanoCoffeeFactory extends CoffeeFactory {
createCoffee() {
new AmericanoCoffee()
}
}
class LatteCoffeeFactory extends CoffeeFactory {
createCoffee() {
new LatteCoffee();
}
}
// 具体工厂创建产品
new AmericanoCoffeeFactory().createCoffee();
new LatteCoffeeFactory().createCoffee();
此时,如果要增加卡布奇诺咖啡,要扩展一个工厂和一种咖啡
// 扩展一个咖啡
class CuppuccinoCoffee{
constructor() {
console.log('LatteCoffee');
}
}
// 扩展一个工厂
class CuppuccinoCoffeeFactory extends CoffeeFactory {
createCoffee() {
new CuppuccinoCoffee();
}
}
// 客户端下单卡布奇诺
new CuppuccinoCoffeeFactory().createCoffee();
相比简单工厂模式,克服了简单工厂的缺点。
抽象工厂模式
但是假如这家咖啡厅是星巴克,客人要点瑞幸的咖啡时,怎么办?
我们把咖啡分成:星巴克美式,星巴克拿铁,瑞幸美式,瑞幸拿铁
和工厂方法对区别,增加对咖啡种类进行抽象。这里涉及到产品族和产品种类的概念。
星巴克和瑞幸是产品族,美式和拿铁是产品种类。是2个维度的概念。
抽象产品->实现产品
抽象工厂->实现工厂->生产多种产品
// 和工厂方法模式的区别:对咖啡种类进行抽象
abstract class AmericanoCoffee {
}
abstract class LatteCoffee{
}
class StarbuckAmericanoCoffee extends AmericanoCoffee{
constructor() {
super();
console.log('StarbuckAmericanoCoffee');
}
}
class StarbuckLatteCoffee extends LatteCoffee{
constructor() {
super();
console.log('StarbuckLatteCoffee');
}
}
class LuckinAmericanoCoffee extends AmericanoCoffee{
constructor() {
super();
console.log('LuckinAmericanoCoffee');
}
}
class LuckinLatteCoffee extends LatteCoffee{
constructor() {
super();
console.log('LuckinLatteCoffee');
}
}
// 和工厂方法模式的区别:一个工厂要做2种咖啡
abstract class CoffeeFactory {
abstract createAmericanoCoffee();
abstract createLattaCoffee();
}
class StarbuckCoffeeFactory extends CoffeeFactory {
createAmericanoCoffee() {
new StarbuckAmericanoCoffee();
}
createLattaCoffee() {
new StarbuckLatteCoffee();
}
}
class LuckinCoffeeFactory extends CoffeeFactory {
createAmericanoCoffee() {
new LuckinAmericanoCoffee();
}
createLattaCoffee() {
new LuckinLatteCoffee();
}
}
new StarbuckCoffeeFactory().createAmericanoCoffee();
new StarbuckCoffeeFactory().createLattaCoffee();
new LuckinCoffeeFactory().createAmericanoCoffee();
new LuckinCoffeeFactory().createLattaCoffee();
此时要增加卡布奇诺咖啡种类,那么要扩展CuppuccinoCoffee抽象类,两个产品族分别扩展CuppuccinoCoffee实现类,抽象工厂要增加(修改)做卡布奇诺的抽象方法,具体工厂要增加(修改)做卡布奇诺的实现方法。
此时,抽象工厂的缺点也暴露出来。增加一个产品种类时,扩展有1+n个,修改有1+n个。n是产品族的个数
abstract class AmericanoCoffee {
}
abstract class LatteCoffee{
}
// 扩展咖啡种类
abstract class CuppuccinoCoffee{
}
class StarbuckAmericanoCoffee extends AmericanoCoffee{
constructor() {
super();
console.log('StarbuckAmericanoCoffee');
}
}
class StarbuckLatteCoffee extends LatteCoffee{
constructor() {
super();
console.log('StarbuckLatteCoffee');
}
}
// 星巴克扩展
class StarbuckCuppuccinoCoffee extends CuppuccinoCoffee{
constructor() {
super();
console.log('StarbuckCuppuccinoCoffee');
}
}
// 瑞幸扩展
class LuckinAmericanoCoffee extends AmericanoCoffee{
constructor() {
super();
console.log('LuckinAmericanoCoffee');
}
}
class LuckinLatteCoffee extends LatteCoffee{
constructor() {
super();
console.log('LuckinLatteCoffee');
}
}
class LuckinCuppuccinoCoffee extends CuppuccinoCoffee{
constructor() {
super();
console.log('LuckinCuppuccinoCoffee');
}
}
abstract class CoffeeFactory {
abstract createAmericanoCoffee();
abstract createLattaCoffee();
// 增加抽象方法
abstract createCuppuccinoCoffee();
}
class StarbuckCoffeeFactory extends CoffeeFactory {
createAmericanoCoffee() {
new StarbuckAmericanoCoffee();
}
createLattaCoffee() {
new StarbuckLatteCoffee();
}
// 增加实现方法
createCuppuccinoCoffee(){
new StarbuckCuppuccinoCoffee();
}
}
class LuckinCoffeeFactory extends CoffeeFactory {
createAmericanoCoffee() {
new LuckinAmericanoCoffee();
}
createLattaCoffee() {
new LuckinLatteCoffee();
}
// 增加实现方法
createCuppuccinoCoffee(){
new LuckinCuppuccinoCoffee();
}
}
new StarbuckCoffeeFactory().createAmericanoCoffee();
new StarbuckCoffeeFactory().createLattaCoffee();
new LuckinCoffeeFactory().createAmericanoCoffee();
new LuckinCoffeeFactory().createLattaCoffee();
new LuckinCoffeeFactory().createCuppuccinoCoffee();
总结:
- 简单工厂模式:
工厂-产品
优点:简单
缺点:违法开闭原则 - 工厂方法模式:
抽象工厂-实现工厂-一种产品
优点:克服简单工厂的缺点
缺点:面对产品族和产品种类问题时,不够抽象 - 抽象工厂模式:
抽象产品-具体产品
抽象工厂-具体工厂-多种产品
优点:针对多个产品族和多个产品种类时,相对来说能抽象清晰的表达多个维度的关系;拓展产品族时,遵循开闭原则
缺点:扩展产品种类时,无法很好地做到开闭原则。需要1+n个修改
网友评论