একাধিক নির্মাণকারীর জন্য জাভাস্ক্রিপ্ট প্যাটার্ন


124

আমার দৃষ্টান্তগুলির জন্য আমার বিভিন্ন নির্মাণকারীর প্রয়োজন need এটির জন্য সাধারণ প্যাটার্ন কী?


দয়া করে কিছুটা সুনির্দিষ্ট করুন আপনি বিভিন্ন পরামিতি সেট সহ নির্মাণকারী চান?
gblazex

জাভাস্ক্রিপ্টে আপনার একাধিক কনস্ট্রাক্টর থাকতে পারে?
ডগ হাউফ

হ্যাঁ এবং না @ ডউগহফ। হ্যাঁ কারণ বোবিন্সের দেওয়া উত্তরটি সমতুল্য আচরণ প্রদানের একটি উপায় সরবরাহ করে। না কারণ আপনি যদি একাধিক স্বতন্ত্র কনস্ট্রাক্টর ফাংশন (প্রতিটি একই প্রোটোটাইপ অবজেক্ট ভাগ করে নিতে চান) কীভাবে প্রোটোটাইপ অবজেক্টের কনস্ট্রাক্টর সম্পত্তি সেট করবেন (যেহেতু কনস্ট্রাক্টর সম্পত্তি কেবলমাত্র একটি নির্মাণকারী ফাংশনকে নির্দেশ করতে পারে)।
মাইকা

3
এই উত্তরগুলির সমস্ত পুরানো / আদর্শ নয়। আমি খুব একটা উত্তর আপ টাইপ করতে অলস, কিন্তু আপনি কার্যকারিতা ও কনস্ট্রাকটর কাছাকাছি একটি বস্তু পাস এবং তারপর ঠিক মত আপনি would আর্গুমেন্ট, যেমন কী ব্যবহার করতে পারেন: function ({ oneThing = 7, otherThing = defaultValue } = {}) { }= {}আমি অতিরিক্ত অতিরিক্ত যা বললাম তা আমি সম্প্রতি শিখেছি, আপনি যদি চান যে ব্যবহারকারী কোনও বিষয় অমান্য না করে এবং সমস্ত ডিফল্ট ব্যবহার করে।
অ্যান্ড্রু

1
ফলোআপ: এই সমস্যাটি সমাধান করার জন্য এখানে কয়েকটি ভাল উপায় রয়েছে: stackoverflow.com/a/32626901/1599699 stackoverflow.com/a/41051984/1599699 stackoverflow.com/a/48287734/1599699 আমি বিশেষত সত্যের জন্য শেষেরটি পছন্দ করি মাল্টিপল কন্সট্রাকটর মত সমর্থন, (কনস্ট্রাকটর যেমন স্ট্যাটিক কারখানা ফাংশন ব্যবহার করে return new this();, return new this.otherStaticFactoryFunction();ইত্যাদি)!
অ্যান্ড্রু

উত্তর:


120

পদ্ধতি বা কনস্ট্রাক্টর সহ জাভাস্ক্রিপ্টের ফাংশন ওভারলোডিং নেই।

আপনি যদি কোনও ফাংশনটি তার কাছে যে প্যারামিটারগুলি পাস করেন তার সংখ্যা এবং ধরণের উপর নির্ভর করে আলাদা আচরণ করতে চান তবে আপনাকে সেগুলি ম্যানুয়ালি শুঁকতে হবে। জাভাস্ক্রিপ্ট আনন্দের সাথে ঘোষিত সংখ্যার আর্গুমেন্টের চেয়ে কম বা কম দিয়ে একটি ফাংশন কল করবে।

function foo(a, b) {
    if (b===undefined) // parameter was omitted in call
        b= 'some default value';

    if (typeof(a)==='string')
        this._constructInSomeWay(a, b);
    else if (a instanceof MyType)
        this._constructInSomeOtherWay(a, b);
}

argumentsআরও কোনও যুক্তি পাস করার জন্য আপনি অ্যারে-মতো হিসাবে অ্যাক্সেস করতে পারেন ।

আপনার যদি আরও জটিল যুক্তিগুলির প্রয়োজন হয় তবে কিছু বা সমস্ত কিছু একটি অবজেক্ট লুকের ভিতরে রাখা ভাল ধারণা হতে পারে:

function bar(argmap) {
    if ('optionalparam' in argmap)
        this._constructInSomeWay(argmap.param, argmap.optionalparam);
    ...
}

bar({param: 1, optionalparam: 2})

পাইথন দেখায় যে ফাংশন ওভারলোডিংয়ের চেয়ে বেশি ব্যবহারিক এবং কৃপিত উপায়ে সর্বাধিক ব্যবহারের ক্ষেত্রে কভার করার জন্য ডিফল্ট এবং নামযুক্ত যুক্তিগুলি কীভাবে ব্যবহার করা যেতে পারে। জাভাস্ক্রিপ্ট, এত কিছু না।


2
ধন্যবাদ, এটি সত্যিই দুর্দান্ত। আমি বলব দ্বিতীয় বিকল্পটি যখন আপনার জটিল যুক্তিগুলি না শুধুমাত্র কার্যকর হয়, তবে সাধারণ-তবুও হার্ড-টু-পার্থক্যযুক্ত যুক্তি যেমন, সমর্থনকারী MyObj({foo: "foo"})প্লাস MyObj({bar: "bar"})। মায়োবজের দুটি কনস্ট্রাক্টর রয়েছে - তবে উভয়েই একটি যুক্তি নিয়েছে যা একটি স্ট্রিং :-)
অ্যালেক্স ডিন

1
এই বিশেষ উদাহরণের জন্য আপনি উদাহরণ কোডে আরও যুক্ত করতে পারেন?
ডগ হাফ

হাই @ ডগহাউফ, ক্রকফোর্ডের বই 'জাভাস্ক্রিপ্ট: দ্য গুড পার্টস' এর 'অবজেক্ট স্পেসিফায়ারস' নামে একটি বিভাগ রয়েছে, প্রচুর উদাহরণ অনলাইনে উল্লেখ করা হয়েছে।
মাইকা

29

আপনি এটি কিভাবে খুঁজে পাবেন?

function Foobar(foobar) {
    this.foobar = foobar;
}

Foobar.prototype = {
    foobar: null
};

Foobar.fromComponents = function(foo, bar) {
    var foobar = foo + bar;
    return new this(foobar);
};

2
এই নতুন (foobar) ফেরত; কাজ করে না আমি রিটার্নে নতুন ফুবার (ফোবার) পরিবর্তন করি; এবং সমস্ত কাজ সঠিক।
isxaker

10
আমি পাই না। আপনি যে কোডটি ব্যবহার করছেন সেখানে আপনি কি যুক্ত করতে পারেন? আপনি কি প্রতি বার সংস্থাগুলি থেকে কল করতে যাচ্ছেন? কারণ এটি সত্যই কোনও নির্মাণকারী নয়, বরং একটি সহায়ক ফাংশন। @ বোবিন্সের উত্তর তখন আরও সঠিক বলে মনে হচ্ছে।
hofnarwillie

1
@ hofnarwillie যদিও একেবারে নিখুঁত নির্মাণকারী নয়, স্থির পদ্ধতি ব্যবহার করে এটি মোটামুটি অনুরূপ সম্পাদন করে যেমন var foobarObj = Foobar.fromComp घटक (foo, বার); বিকল্প আর্গুমেন্ট সহ আপনার একটি নতুন অবজেক্ট তৈরি করা দরকার।
নাথান উইলিয়ামস

20

আপনি স্থিতিশীল পদ্ধতি সহ ক্লাস ব্যবহার করতে পারেন যা সেই শ্রেণীর উদাহরণ দেয়

    class MyClass {
        constructor(a,b,c,d){
            this.a = a
            this.b = b
            this.c = c
            this.d = d
        }
        static BAndCInstance(b,c){
            return new MyClass(null,b,c)
        }
        static BAndDInstance(b,d){
            return new MyClass(null,b, null,d)
        }
    }

    //new Instance just with a and other is nul this can
    //use for other params that are first in constructor
    const myclass=new MyClass(a)

    //an Instance that has b and c params
    const instanceWithBAndC = MyClass.BAndCInstance(b,c)

    //another example for b and d
    const instanceWithBAndD = MyClass.BAndDInstance(b,d)

এই নিদর্শন দিয়ে আপনি একাধিক কনস্ট্রাক্টর তৈরি করতে পারেন


3
এটি সেরা উত্তর। অন্যরা অ্যারে পার্স করা এবং একগুচ্ছ অপ্রয়োজনীয় কাজ করে।
ব্লেন টাউনসেন্ড

13

বোবিন্সের উত্তরের মতো এটি হাতছাড়া করার মতো মনে হয়নি, তাই আমি jQuery এর প্লাগইন বিকল্পগুলির প্যাটার্নটি পুরোপুরি ছিটিয়ে দিয়েছি।

এখানে কনস্ট্রাক্টর:

//default constructor for Preset 'class'
function Preset(params) {
    var properties = $.extend({
        //these are the defaults
        id: null,
        name: null,
        inItems: [],
        outItems: [],
    }, params);

    console.log('Preset instantiated');
    this.id = properties.id;
    this.name = properties.name;
    this.inItems = properties.inItems;
    this.outItems = properties.outItems;
}

এখানে ইনস্ট্যান্টেশনের বিভিন্ন উপায় রয়েছে:

presetNoParams = new Preset(); 
presetEmptyParams = new Preset({});
presetSomeParams = new Preset({id: 666, inItems:['item_1', 'item_2']});
presetAllParams = new Preset({id: 666, name: 'SOpreset', inItems: ['item_1', 'item_2'], outItems: ['item_3', 'item_4']});

এবং এটি যা তৈরি করেছে তা এখানে:

presetNoParams
Preset {id: null, name: null, inItems: Array[0], outItems: Array[0]}

presetEmptyParams
Preset {id: null, name: null, inItems: Array[0], outItems: Array[0]}

presetSomeParams
Preset {id: 666, name: null, inItems: Array[2], outItems: Array[0]}

presetAllParams
Preset {id: 666, name: "SOpreset", inItems: Array[2], outItems: Array[2]}


10

ইরিসিফর্মের উত্তর নিয়ে আরও এগিয়ে যাওয়া, আপনি newআপনার initপদ্ধতিটিকে আপনার কলটি চেইন করতে পারেন ।

function Foo () {
    this.bar = 'baz';
}

Foo.prototype.init_1 = function (bar) {
    this.bar = bar;
    return this;
};

Foo.prototype.init_2 = function (baz) {
    this.bar = 'something to do with '+baz;
    return this;
};

var a = new Foo().init_1('constructor 1');
var b = new Foo().init_2('constructor 2');

সুতরাং মূলত আপনি এখানে যা করছেন তা হ'ল অবু অবজেক্টটি গ্রহণ করছে এবং তারপরে প্রোটোটাইপ ফাংশনগুলির সাথে আর DI_1 এবং init_2 পরামিতিগুলিকে কল করবে। আপনার init_1 এবং init_2 এর সাথে শব্দটির কাজ করা উচিত।
ডগ হাউফ

প্রথম ফু ()) এর পরে কি সেখানে একটি আধা-কোলন থাকতে হবে?
ডগ হাফ

ধন্যবাদ ডগ, আমি পরিবর্তন করেছি।
হাসতে হাসতে

আপনি কি নিশ্চিত যে এটি কাজ করে? আমি একসাথে চেইন করতে new Foo()এবং কল করতে initসক্ষম হইনি কারণ আমি বস্তুগুলিতে বৈশিষ্ট্য অ্যাক্সেস করতে সক্ষম নই। আমাকে দৌড়াতে হয়েছিলvar a = new Foo(); a.init_1('constructor 1');
মিলি স্মিথ

@ মিলি স্মিথ আমি স্বীকার করব যে আমি এখন কিছুক্ষণের জন্য জেএস লিখিনি ... তবে আমি কেবল এই কোডটি Chrome জেএস কনসোলটিতে পেস্ট করেছি এবং নতুন থেকে শুরু করে চেইনটি কাজ করেছে।
laughingbovine

3

কখনও কখনও, পরামিতিগুলির জন্য ডিফল্ট মানগুলি একাধিক কনস্ট্রাক্টরের পক্ষে যথেষ্ট। এবং যখন এটি পর্যাপ্ত হয় না, তখন আমি বেশিরভাগ কনস্ট্রাক্টরের কার্যকারিতা একটি init (অন্যান্য-প্যারাম) ফাংশনে আবদ্ধ করার চেষ্টা করি যা পরে বলা হয়। এমন কোনও বস্তু তৈরি করতে কারখানার ধারণাটি ব্যবহার করার বিষয়টিও বিবেচনা করুন যা আপনার পছন্দসই অন্যান্য বস্তুগুলি কার্যকরভাবে তৈরি করতে পারে।

http://en.wikipedia.org/w/index.php?title=Factory_method_pattern&oldid=363482142#Javascript


1
কারখানা পদ্ধতিটি একটি ভাল সমাধান বলে মনে করে - এটি আলাদা কারখানার শ্রেণির ব্যবহারের সাথে বিভ্রান্ত না করার বিষয়ে নিশ্চিত হন, যা সম্ভবত ব্যবহারের ক্ষেত্রে সম্পূর্ণ অপ্রাসঙ্গিক।
সাইমন গ্রোনিওল্ট

1
সেই লিঙ্কটি কোথাও যায় না। এই পৃষ্ঠায় কোনও জাভাস্ক্রিপ্ট অ্যাঙ্কর নেই।
রব

3

উত্তর দেওয়া হচ্ছে কারণ এই প্রশ্নটি গুগলে প্রথমে ফিরে এসেছে তবে উত্তরগুলি এখন পুরানো।

আপনি ES6 এ কনস্ট্রাক্টর পরামিতি হিসাবে ডিস্ট্রাকচারিং অবজেক্টগুলি ব্যবহার করতে পারেন

প্যাটার্নটি এখানে:

আপনার একাধিক কনস্ট্রাক্টর থাকতে পারে না তবে আপনি যা চান তা করতে আপনি ডিস্ট্রাকচারিং এবং ডিফল্ট মানগুলি ব্যবহার করতে পারেন।

export class myClass {

  constructor({ myArray = [1, 2, 3], myString = 'Hello World' }) {

    // ..
  }
}

আপনি যদি কোনও 'প্যারামিটারলেস' কনস্ট্রাক্টরকে সমর্থন করতে চান তবে আপনি এটি করতে পারেন।

export class myClass {

      constructor({myArray = [1, 2, 3], myString = 'Hello World'} = {}) {

        // ..
      }
}

2
export default class Order {

    static fromCart(cart) {
        var newOrder = new Order();
        newOrder.items = cart.items;
        newOrder.sum = cart.sum;

        return newOrder;
    }

    static fromOrder(id, order) {
        var newOrder = new Order();
        newOrder.id = id;
        newOrder.items = order.items;
        newOrder.sum = order.sum;

        return newOrder;
    }
}

Useges:

  var newOrder = Order.fromCart(cart)
  var newOrder = Order.fromOrder(id, oldOrder)

0

এটি জাভাস্ক্রিপ্ট এবং CSS3 - পরীক্ষার রেফ সহ HTML5প্রোগ্রামিংয়ের একাধিক কনস্ট্রাক্টরের জন্য দেওয়া উদাহরণ ।

function Book() {
    //just creates an empty book.
}


function Book(title, length, author) {
    this.title = title;
    this.Length = length;
    this.author = author;
}

Book.prototype = {
    ISBN: "",
    Length: -1,
    genre: "",
    covering: "",
    author: "",
    currentPage: 0,
    title: "",

    flipTo: function FlipToAPage(pNum) {
        this.currentPage = pNum;
    },

    turnPageForward: function turnForward() {
        this.flipTo(this.currentPage++);
    },

    turnPageBackward: function turnBackward() {
        this.flipTo(this.currentPage--);
    }
};

var books = new Array(new Book(), new Book("First Edition", 350, "Random"));

আর অপরিচ্ছন্নতা? প্রোটোটাইপ ব্যবহার করে সম্পত্তিগুলিকে জনসম্মুখে রাখে, তাই না?
গ্যাব্রিয়েল সিমাস

6
এটা ভুল। আপনার দ্বিতীয় নির্মাতার সংজ্ঞাটি প্রথমটিকে ওভাররাইড করে, সুতরাং যখন আপনি পরে নতুন বুক () কল করবেন তখন আপনি সমস্ত প্যারামিটারের মান অপরিজ্ঞায়িত করে সেট করে দ্বিতীয় কনস্ট্রাক্টরকে কল করছেন।
এরোনসফ্যাটালিটি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.