可組合的類定義

我們定義類時,爐牆代碼,和業務代碼常常耦合在一起,本文是將業務代碼和爐牆代碼解耦。利用類繼承的特性。

一個常用的構造類的模式是流利模式,或者方法鏈,耦合的代碼如下:

    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, })