質問

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.

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. This way you also get rid of the undesired function names (Clerk, Manager and Teacher).

Also, you should create the constructors object only once and reuse it in the create. 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 :-)


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帰属
所属していません StackOverflow
scroll top