我应该如何推进重构此代码?

时间:2017-01-05 01:13:40

标签: javascript design-patterns abstraction repeat

所以我正在研究一个侧面项目的Web应用程序,它允许您在一个网站上跟踪来自多个公司的软件包。即您可以输入任何跟踪号码,服务器将检查其格式并吐出相应的跟踪信息。

Click here to see my file directory!

我决定推进策略模式 facade ,因为我认为它可以很好地满足应用程序的目的。

以上是我目前的回购。

结构将是:

客户 - > DeliveryFacade - > DeliveryController - > TrackingInterface - >各种公司API(FedEx,CanadaPost,UPS)。

我正在处理 DeliveryController ,并遇到一些有臭味的代码,因为我正在处理它。

就是这样:

export default class DeliveryController{

    /** Checks the format of tracking number to determine the shipping company it
     *  has been given. If the tracking number is able to be validated, then return
     *  the correct shipping company. If it is not able to be validated (not a string), return
     *  null.
     *
     *  @params trackingNumber  : string
     *  @return shippingCompany : string
     *
     *  e.g. returns "Fedex" , "CanadaPost", "UPS"
     *  */
    public checkFormat(trackingNumber : string) : string{

        if (typeof trackingNumber == "string" || trackingNumber instanceof String) {

            // CanadaPost
            if (/{regex}/.test(trackingNumber)){
                return "CanadaPost";
            }

            // FedEx
            if (/{regex}/.test(trackingNumber)) {
                return "FedEx";
            }
            // UPS
            if (/{regex}/.test(trackingNumber)) {
                return "UPS";
            }
        }
        else return null;
    }

    /** Processes a tracking number and returns a deliveryInfo.
     *  @param trackingNumber
     *  @return deliveryInfo
     */

    public process(trackingNumber : string) : deliveryInfo{
        var company = this.checkFormat(trackingNumber);
        switch (company){
            case "CanadaPost":
                break;
            case "FedEx":
                break;
            case "UPS":
                break;
        }
        return /*some deliveryInfo*/;
    }

我的问题是:有什么方法可以消除每种策略的明显重复?

如果我想从新类型的公司添加新的跟踪号格式,我必须在我的跟踪策略文件夹中添加一个新类,然后我必须将这些案例添加到checkFormat和process(这显然是未完成的)。

我可以用某种形式的抽象来避免这种情况吗?

1 个答案:

答案 0 :(得分:0)

您忘了提到您使用的是TypeScript。

我会做那样的事情:

interface IDeliveryCompany {
     tackingNumberMatch(trackingNumber: string): boolean;
     process(): void;
}

class UPSDeliveryCompany implements IDeliveryCompany {

     trackingNumberMatch(trackingNumber: string): boolean {
         return /{regex}/.test(trackingNumber);
     }

     process(): void {
          // ... do the processing
     }
}

// ... similar other delivery companies ...

class DeliveryCompanyFactory {

    private _companies: Array<IDeliveryCompany>;

    constructor() {
        _companies = [
            new UPSDeliveryCompany(),
            new CanadaPostDeliveryCompany(),
            new FedExDeliveryCompany()
        ];
    }

    getCompany(trackingNumber: string): IDeliveryCompany {
        return this._companies.find((c) => c.trackingNumberMatch(trackingNumber));
    }
}

/// example usage:
const factory = new DeliveryCompanyFactory();
factory.getCompany("some_tracking_number").process();

这样,当您需要添加新的交付公司时,您将不得不为其创建一个新类,它将封装该交付公司的所有逻辑,并将其实例添加到{{1} }。

如果您有一些对所有交付公司都很常见的逻辑,那么您可以将DeliveryCompanyFactory接口替换为具有通用逻辑的IDeliveryCompany基类。