পাইথন ফ্যাক্টরি ফাংশন সেরা অনুশীলন


30

ধরুন আমার কাছে ক্লাসযুক্ত একটি ফাইল foo.pyরয়েছে Foo:

class Foo(object):
   def __init__(self, data):
      ...

এখন আমি এমন একটি ফাংশন যুক্ত করতে চাই যা Fooকাঁচা উত্স ডেটা থেকে নির্দিষ্ট উপায়ে একটি বস্তু তৈরি করে। আমি কি এটিকে ফু-তে স্থিতিশীল পদ্ধতি হিসাবে বা অন্য কোনও পৃথক ফাংশন হিসাবে রেখে দেব?

class Foo(object):
   def __init__(self, data):
      ...
# option 1:
   @staticmethod
   def fromSourceData(sourceData):
      return Foo(processData(sourceData))

# option 2:
def makeFoo(sourceData):
   return Foo(processData(sourceData))

ব্যবহারকারীদের পক্ষে সুবিধাজনক হওয়া আরও বেশি গুরুত্বপূর্ণ কিনা তা আমি জানি না:

foo1 = foo.makeFoo(sourceData)

বা পদ্ধতি এবং শ্রেণীর মধ্যে স্পষ্ট মিলন বজায় রাখা আরও গুরুত্বপূর্ণ কিনা:

foo1 = foo.Foo.fromSourceData(sourceData)

উত্তর:


45

পছন্দটি কারখানার ফাংশন এবং পরিবর্তে তৃতীয় বিকল্পের মধ্যে হওয়া উচিত ; ক্লাস পদ্ধতি:

class Foo(object):
   def __init__(self, data):
      ...

   @classmethod
   def fromSourceData(klass, sourceData):
      return klass(processData(sourceData))

শ্রেণিবদ্ধ কারখানাগুলির অতিরিক্ত সুবিধা রয়েছে যে তারা উত্তরাধিকারসূত্রে রয়েছে। আপনি এখন একটি সাবক্লাস তৈরি করতে পারেন Foo, এবং উত্তরাধিকার সূত্রে প্রাপ্ত ফ্যাক্টরি পদ্ধতিটি সেই সাবক্লাসের উদাহরণ তৈরি করবে।

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

নিম্নলিখিত দুটি বিকল্পের তুলনা করুন:

foo.Foo.fromFrobnar(...)
foo.Foo.fromSpamNEggs(...)
foo.Foo.someComputedVersion()
foo.Bar.fromFrobnar(...)
foo.Bar.someComputedVersion()

বনাম

foo.createFooFromFrobnar()
foo.createFooFromSpamNEggs()
foo.createSomeComputedVersionFoo()
foo.createBarFromFrobnar()
foo.createSomeComputedVersionBar()

আরও ভাল, আপনার শেষ ব্যবহারকারীটি কেবল Fooশ্রেণিটি আমদানি করতে এবং এটি তৈরির বিভিন্ন উপায়ে ব্যবহার করতে পারে, কারণ আপনার কাছে কারখানার সমস্ত পদ্ধতি এক জায়গায় রয়েছে:

from foo import Foo
Foo()
Foo.fromFrobnar(...)
Foo.fromSpamNEggs(...)
Foo.someComputedVersion()

Stdlib datetimeমডিউলটি ক্লাস মেথড ফ্যাক্টরিগুলি ব্যাপকভাবে ব্যবহার করে এবং এটির এপিআই এটি আরও পরিষ্কার।



শেষ ব্যবহারকারীর কার্যকারিতার উপর দুর্দান্ত ফোকাস
drtf

1

পাইথনে, আমি সাধারণত কারখানার পদ্ধতিগুলির চেয়ে শ্রেণিক শ্রেণিবিন্যাস পছন্দ করি। কিছুটা এইরকম:

class Foo(object):
    def __init__(self, data):
        pass

    def method(self, param):
        pass

class SpecialFoo(Foo):
    def __init__(self, param1, param2):
        # Some processing.
        super().__init__(data)

class FromFile(Foo):
    def __init__(self, path):
        # Some processing.
        super().__init__(data)

বলুন, আমি পুরো শ্রেণিবিন্যাস (এবং কেবল এটিই) একটি মডিউলে রেখে দেব, বলুন foos.py। বেস ক্লাস Fooসাধারণত সমস্ত পদ্ধতি প্রয়োগ করে (এবং যেমন ইন্টারফেস), এবং সাধারণত ব্যবহারকারীরা সরাসরি নির্মিত হয় না। সাবক্লাসগুলি বেস কন্সট্রাক্টরকে ওভাররাইট করার একটি মাধ্যম, এবং কীভাবে Fooনির্মাণ করা যায় তা নির্দিষ্ট করে । তারপরে আমি Fooউপযুক্ত কনস্ট্রাক্টরকে ফোন করে একটি তৈরি করব , যেমন:

foo1 = mypackage.foos.SpecialFoo(param1, param2)
foo2 = mypackage.foos.FromFile('/path/to/foo')

স্থির পদ্ধতি, শ্রেণি পদ্ধতি বা মডিউল-স্তরের কার্যাবলী থেকে তৈরি কারখানাগুলির চেয়ে আমি এটি আরও মার্জিত এবং নমনীয় মনে করি find

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.