打字稿-是否可以解决以下问题?

时间:2020-06-12 17:08:41

标签: javascript typescript oop builder

我有这段代码,我试图将其从Java转换为打字稿。它使用Composite设计模式和Abstract Builder模式。看来我可以翻译约90%的内容,但是有些东西要么不美观,要么在功能上存在问题。

复合层次结构如下:

AbstractLine->由MarketMarketLine

实现

AbstractCompositeLine->由LinesMarketCompositeMarketLine

实现

下面这段代码的简单用例是:

const market = new MarketBuilder(new MarketSpecifier("123"))
    .withMargin(new Margin(123))
    .build();

const linesMarket = new LinesMarketBuilder(new MarketSpecifier("123"))
                        .withMargin(new Margin(123))
                        .addLine(
                            new CompositeMarketLineBuilder(new MarketLineSpecifier("123-1"))
                                .withMargin(new Margin(456))
                                .addLine(
                                    new MarketLineBuilder(new MarketLineSpecifier("123-1-1"))
                                        .build()
                                )
                                .addLine(
                                    new MarketLineBuilder(new MarketLineSpecifier("123-1-2"))
                                        .build()
                                )
                                .build()
                        )
                        .build();

这些是我遇到的问题:

  1. AbstractLineBuilder内,所有属性都必须公开,以便我访问AbstractLine构造函数中的那些道具。是否有可能制作这个道具。私人/受保护的,仅AbstractLineBuilder可以访问?
  2. Map<MarketLineSpecifier, Line<any>>->如何使any实际上像Java中的? extends MarketLineSpecifier?还有其他类型安全的解决方法吗?
  3. Market内,我有public constructor。是否可以将其设为私有且仅MarketBuilder可以访问?

代码在这里:

class Margin{
    private readonly value : number;

    constructor(value: number) {
        this.value = value;
    }
}

interface LineSpecifier {
    value() : string;
}

class MarketSpecifier implements LineSpecifier{
    private readonly _value: string;

    constructor(value: string) {
        this._value = value;
    }

    value(): string {
        return this._value;
    }
}

class MarketLineSpecifier implements LineSpecifier{
    private readonly _value : string;

    constructor(value: string) {
        this._value = value;
    }

    value(): string {
        return this._value;
    }
}

interface Line<T extends LineSpecifier> {
    specifier() : T;
    calculateMostBalancedLine() : Line<T>;
}

abstract class AbstractLine<T extends LineSpecifier> implements Line<T>{
    protected readonly _specifier : T;
    protected _margin? : Margin;

    protected constructor(builder : AbstractLineBuilder<T,any>){
        this._specifier = builder._specifier;
        this._margin = builder._margin;
    }

    calculateMostBalancedLine(): Line<T>{
        return this;
    }

    specifier(): T{
        return this._specifier;
    }
}

abstract class AbstractLineBuilder<T extends LineSpecifier, S extends AbstractLineBuilder<T,S>>{
    public _specifier : T;  //TODO: how to make this private and accessible only in AbstractLine constructor ??
    public _margin? : Margin;

    public constructor(specifier : T){
        this._specifier = specifier;
    }

    public withMargin(margin : Margin) : S{
        this._margin = margin;
        return this.self();
    }

    protected abstract build() : AbstractLine<T>;

    //simulated self-type idiom
    protected abstract self() : S;
}

//----

abstract class AbstractCompositeLine<T extends LineSpecifier> implements Line<T>{
    protected readonly _specifier : T;
    protected _margin? : Margin;
    protected readonly _lines : Map<MarketLineSpecifier, Line<any>>;    //TODO: any should be "? extends MarketLineSpecifier"

    protected constructor(builder : AbstractCompositeLineBuilder<T,any>){
        this._specifier = builder._specifier;
        this._margin = builder._margin;
        this._lines = builder._lines;
    }

    calculateMostBalancedLine(): Line<T>{
        return this._lines.get(new MarketLineSpecifier("123"))!;
    }

    specifier(): T{
        return this._specifier;
    }
}

abstract class AbstractCompositeLineBuilder<T extends LineSpecifier, S extends AbstractCompositeLineBuilder<T,S>>{
    public _specifier : T;
    public _margin? : Margin;
    public _lines : Map<MarketLineSpecifier, Line<MarketLineSpecifier>> = new Map();

    public constructor(specifier : T){
        this._specifier = specifier;
    }

    public withMargin(margin : Margin) : S{
        this._margin = margin;
        return this.self();
    }

    public addLine(line : Line<MarketLineSpecifier>) : S{
        this._lines.set(line.specifier(), line);
        return this.self();
    }

    protected abstract build() : AbstractCompositeLine<T>;

    protected abstract self() : S;
}

//----

class Market extends AbstractLine<MarketSpecifier> {
     public constructor(builder : MarketBuilder){   //TODO: this should be private and accessible to MarketBuilder
         super(builder);
     }
}

//TODO: make this inner class of Market so it can be used only as Market.MarketBuilder?
class MarketBuilder extends AbstractLineBuilder<MarketSpecifier, MarketBuilder>{
    public constructor(specifier : MarketSpecifier){
        super(specifier);
    }

    public build(): Market {
        return new Market(this);
    }

    protected self(): MarketBuilder {
        return this;
    }

}

//----

class MarketLine extends AbstractLine<MarketLineSpecifier>{
    public constructor(builder : MarketLineBuilder){
        super(builder);
    }
}

class MarketLineBuilder extends AbstractLineBuilder<MarketLineSpecifier, MarketLineBuilder>{
    public constructor(specifier : MarketLineSpecifier){
        super(specifier);
    }

    public build(): MarketLine {
        return new MarketLine(this);
    }

    protected self(): MarketLineBuilder {
        return this;
    }
}

//----

class LinesMarket extends AbstractCompositeLine<MarketSpecifier> {
    public constructor(builder : LinesMarketBuilder){
        super(builder);
    }
}

class LinesMarketBuilder extends AbstractCompositeLineBuilder<MarketSpecifier, LinesMarketBuilder>{
    public constructor(specifier : MarketSpecifier){
        super(specifier);
    }

    public build(): LinesMarket {
        return new LinesMarket(this);
    }

    protected self(): LinesMarketBuilder {
        return this;
    }

}

//----

class CompositeMarketLine extends AbstractCompositeLine<MarketLineSpecifier> {
    public constructor(builder : CompositeMarketLineBuilder){
        super(builder);
    }
}

class CompositeMarketLineBuilder extends AbstractCompositeLineBuilder<MarketLineSpecifier, CompositeMarketLineBuilder>{
    public constructor(specifier : MarketLineSpecifier){
        super(specifier);
    }

    public build(): CompositeMarketLine {
        return new CompositeMarketLine(this);
    }

    protected self(): CompositeMarketLineBuilder {
        return this;
    }

}

0 个答案:

没有答案