可组合的类定义

我们定义类时,炉墙代码,和业务代码常常耦合在一起,本文是将业务代码和炉墙代码解耦。利用类继承的特性。

一个常用的构造类的模式是流利模式,或者方法链,耦合的代码如下:

    class Cake {
        setFlavour(flavour) {
            this.flavour = flavour;
            return this
        }
        setLayers(layers) {
            this.layers = layers;
            return this
        }
        bake() {
            // do some baking
            return this
        }
    }

    const cake = new Cake()

    cake.
        setFlavour('chocolate').
        setLayers(3).
        bake();

    expect(cake).toEqual({ flavour: "chocolate", layers: 3, })

这里,每个方法的赋值代码是业务代码,最后返回本实例是框架代码,混合在一起的代码阅读难度增加很多。我们将其分离,首先,基类只写业务代码:

    class Cake {
        setFlavour(flavour) {
            this.flavour = flavour;
        }
        setLayers(layers) {
            this.layers = layers;
        }
        bake() {
            // do some baking
        }
    }

然后,我们写流利模式代码:

    class FluentCake extends Cake {
        setFlavour(flavour) {
            super.setFlavour(flavour)
            return this
        }
        setLayers(layers) {
            super.setLayers(layers)
            return this
        }
        bake() {
            // do some baking
            super.bake()
            return this
        }
    }

分离后的代码,更加清晰可读。

用法是一样的:

    const cake = new FluentCake()

    cake.
        setFlavour('chocolate').
        setLayers(3).
        bake();

    expect(cake).toEqual({ flavour: "chocolate", layers: 3, })

javascript中,超类和子类也可以解耦:

    const Fluent = (superclass) => class Fluent extends superclass {
        setFlavour(flavour) {
            super.setFlavour(flavour)
            return this
        }
        setLayers(layers) {
            super.setLayers(layers)
            return this
        }
        bake() {
            // do some baking
            super.bake()
            return this
        }
    }

使用方法如下:

    const FluentCake = Fluent(Cake)

    const cake = new FluentCake()
    cake.
        setFlavour('chocolate').
        setLayers(3).
        bake();
    expect(cake).toEqual({ flavour: "chocolate", layers: 3, })