跳转到内容

抽象工厂模式

首发于:2022-03-22

基本概念

抽象工厂(Abstract Factory):通过对类的工厂抽象使其业务用于对产品类簇的创建,而不是负责创建某一类产品的实例。关键在于使用抽象类制定了实例的结构,调用者直接面向实例的结构编程,从实例的具体实现中解耦。

现实生活中的例子

还是上次那个饭店的例子,当然饭店可以有很多个,也不一定非要去这一家,而每一家饭店又都有自己的特色菜,饭店有菜,有汤,还有面食等各种这样的食物,菜都可以吃,汤都可以喝,面都可以嗦。

上面的场景都属于抽象工厂的场景,食物可以被抽象,饭店也可以被抽象。

应用场景

如果一组实例都有相同的结构,那么就可以使用抽象工厂模式。

优缺点

优点:

  1. 抽象产品类将产品的结构抽象出来,访问者不需要知道产品的具体实现,只需要面向产品的结构编程即可,从产品的具体实现中解耦

缺点:

  1. 扩展新类簇的产品类比较困难,因为需要创建新的抽象产品类,并且还要修改工厂类,违反开闭原则;
  2. 带来了系统复杂度,增加了新的类,和新的继承关系;

实现

抽象工厂创建饭店

因为 js 没有抽象类,所以用 ts 来实现。

ts
abstract class Restaurant {
    name: string = '';
    menu: Record<string, Dish> = {};
    order(name: string) {
        if (this.menu[name]) {
            return this.menu[name];
        }
        console.log('没这个菜了');
        return null;
    }

    addMenu(name: string, food: Food) {
        this.menu[name] = food;
    }
}

abstract class Food {
    name: string = '';
    eatMethod: string = 'eat';
    eat() {
        console.log(`${this.eatMethod} ${this.name}`);
    }
}

class Dish extends Food {
    constructor() {
        super();
        this.name = '小炒黄牛肉';
    }
}

class Soup extends Food {
    constructor() {
        super();
        this.eatMethod = 'drink';
        this.name = '紫菜蛋花汤';
    }
}

class Noodle extends Food {
    constructor() {
        super();
        this.eatMethod = 'suck';
        this.name = '阳春面';
    }
}

class Restaurant1 extends Restaurant{
    constructor(name: string) {
        super();
        this.name = name;
    }
}

class Restaurant2 extends Restaurant{
    constructor(name: string) {
        super();
        this.name = '高级饭店' + name;
    }
}

const r1 = new Restaurant1('r1');
console.log(r1.name);
r1.addMenu('yangchunmian', new Noodle());
r1.addMenu('xiaochaohuangniurou', new Dish());
r1.addMenu('zicaidanhuatang', new Soup());

r1.order('yangchunmian')?.eat();
r1.order('xiaochaohuangniurou')?.eat();
r1.order('yuxiangrousi')?.eat();

const r2 = new Restaurant2('r2');
console.log(r2.name);
r2.addMenu('yangchunmian', new Noodle());
r2.addMenu('xiaochaohuangniurou', new Dish());
r2.addMenu('zicaidanhuatang', new Soup());

r2.order('yangchunmian')?.eat();
r2.order('xiaochaohuangniurou')?.eat();
r2.order('zicaidanhuatang')?.eat();

京ICP备18043750号