简体   繁体   English

没有if-else块的JavaScript Factory模式

[英]JavaScript Factory pattern without if-else block

I was wondering if there is a better way to implement the createEmployee() that uses a dictionary or some other way to quickly lookup the type being requested rather than the if-else block. 我想知道是否有更好的方法来实现使用字典的createEmployee()或其他方法来快速查找所请求的类型,而不是if-else块。

function Clerk( options ) {
            this.hourRate = options.hourRate || 20;
            this.firstName = options.firstName || "no first name";
            this.lastName = options.lastName || "no last name";
            this.id = options.id || "-9999999999";
        }

        function Manager( options) {
            this.hourRate = options.hourRate || 200;
            this.firstName = options.firstName || "no first name";
            this.lastName = options.lastName || "no last name";
            this.id = options.id || "-9999999999";
            this.yearBonus = options.yearBonus || "200000";
        }

        function Teacher( options) {
            this.hourRate = options.hourRate || 100;
            this.firstName = options.firstName || "no first name";
            this.lastName = options.lastName || "no last name";
            this.id = options.id || "-9999999999";
            this.subject = options.subject || "history";
        }

        var EmployeesFactory = function() {};

        EmployeesFactory.prototype.createEmployee = function (options) {
            if(options.employeeType == "Clerk")
                employeeConstructor = Clerk;
            else if(options.employeeType == "Manager")
                employeeConstructor = Manager;
            else if(options.employeeType == "Teacher")
                employeeConstructor = Teacher;
            return new employeeConstructor(options);
        }

        var factory = new EmployeesFactory();
        var person = factory.createEmployee( {
            employeeType: "Manager",
            firstName: "Haim",
            lastName: "Michael",
            id: 234234234 } );

        document.write(person instanceof Manager);

Try this: 尝试这个:

var constructors;

constructors = {
    "Clerk" : function (options) {
        // your constructor code here for clerks
    },
    "Manager" : function (options) {
        // your constructor code here for managers
    },
    "Teacher" : function (options) {
        // your constructor code here for teachers
    }
};

EmployeesFactory.prototype.createEmployee = function (options) {
    return constructors[options.employeeType](options);
};

I recommend keeping the constructors object well hidden inside EmployeesFactory . 我建议将constructors对象很好地隐藏在EmployeesFactory This way you also get rid of the undesired function names ( Clerk , Manager and Teacher ). 这样,您还可以摆脱不需要的函数名称( ClerkManagerTeacher )。

Also, you should create the constructors object only once and reuse it in the create. 另外,您应该只创建一次constructors对象,然后在创建过程中重用它。 Don't instantiate it in the create. 不要在创建中实例化它。 You can do this in the following way: 您可以通过以下方式执行此操作:

var EmployeesFactory = function () {
    var constructors;

    constructors = {
        "Clerk" : function (options) {
            // your constructor code here for clerks
        },
        "Manager" : function (options) {
            // your constructor code here for managers
        },
        "Teacher" : function (options) {
            // your constructor code here for teachers
        }
    };

    return {
        "create" : function (options) {
            return constructors[options.employeeType](options);
        }
    };
};

You get the factory this way: 您可以通过以下方式获得工厂:

factory = EmployeesFactory();

And can create stuff this way: 并可以通过以下方式创建东西:

factory.create(options);

All will be cozy and hidden inside the outer enveloping closure with no guts hanging outside. 一切都将舒适且隐藏在外部的封口内,没有胆量挂在外面。

The intention of the Factory Pattern is to hide the complexity and details of object construction, so keeping the methods around for consumption is missing out on an aspect (I admit, minor/minimal) of the pattern. 工厂模式的目的是隐藏的复杂性和对象结构的细节,因此保持方法各地的消费是错过了一个方面(我承认,未成年人/最小)的格局。 By using closures you'll get the benefits of the hiding, too. 通过使用闭包,您还将获得隐藏的好处。

Yes, as you said, use a dictionary: 是的,正如您所说,请使用字典:

function createEmployee(options) {
    return new {
        "Clerk": Clerk,
        "Manager": Manager,
        "Teacher": Teacher
    }[options.employeeType](options);
}

Maybe make the object literal a static variable constructors , and re-introduce the intermediate employeeConstructor variable for more verbosity and less confusing syntax :-) 也许使对象文字成为静态变量constructors ,然后重新引入中间的employeeConstructor变量,以获得更多的详细信息和更少的混乱语法:-)


Btw, there's lots of code duplication in your constructors. 顺便说一句,您的构造函数中有很多代码重复。 You could make that more DRY: 您可以使它更干燥:

function Employee(options, defaultRate) {
    this.hourRate = options.hourRate || defaultRate;
    this.firstName = options.firstName || "no first name";
    this.lastName = options.lastName || "no last name";
    this.id = options.id || "-9999999999";
}

function Clerk(options) {
    Employee.call(this, options, 20);
}
function Manager(options) {
    Employee.call(this, options, 200);
    this.yearBonus = options.yearBonus || "200000";
}
function Teacher(options) {
    Employee.call(this, options, 100);
    this.subject = options.subject || "history";
}

Yes, the below will be cleaner code. 是的,下面将是更干净的代码。

// Create this one time
var constructors = {};

constructors["Manager"] = Manager
constructors["Teacher"] = Teacher
...

// Each object
return new constructors[options.employeeType](options);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM