我有这段代码,我试图将其从Java转换为打字稿。它使用Composite设计模式和Abstract Builder模式。看来我可以翻译约90%的内容,但是有些东西要么不美观,要么在功能上存在问题。
复合层次结构如下:
AbstractLine
->由Market
和MarketLine
AbstractCompositeLine
->由LinesMarket
和CompositeMarketLine
下面这段代码的简单用例是:
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();
这些是我遇到的问题:
AbstractLineBuilder
内,所有属性都必须公开,以便我访问AbstractLine
构造函数中的那些道具。是否有可能制作这个道具。私人/受保护的,仅AbstractLineBuilder
可以访问?Map<MarketLineSpecifier, Line<any>>
->如何使any
实际上像Java中的? extends MarketLineSpecifier
?还有其他类型安全的解决方法吗?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;
}
}