বিভিন্ন ইনপুট পরামিতি সহ কর্মীদের জন্য সি # ডিজাইনের প্যাটার্ন


14

আমি নিশ্চিত না কোন ডিজাইনের প্যাটার্নটি আমাকে এই সমস্যাটি সমাধান করতে সহায়তা করতে পারে।

আমার একটি 'কোর্ডিনেটর' শ্রেণি রয়েছে যা নির্ধারণ করে যে কোন শ্রমিক শ্রেণিটি ব্যবহার করা উচিত - সেখানে কর্মরত বিভিন্ন ধরণের শ্রমিকদের সম্পর্কে না জেনে - এটি কেবল একটি ওয়ার্কারফ্যাক্টরি কল করে এবং সাধারণ আই ওয়ার্কার ইন্টারফেসে কাজ করে।

এরপরে এটি উপযুক্ত কর্মীকে কাজ করার জন্য সেট করে এবং তার 'ডুওর্ক' পদ্ধতির ফলাফল প্রদান করে।

এটা ঠিক আছে ... এখনও অবধি; আমাদের একটি নতুন ওয়ার্কার ক্লাস, "ওয়ার্কারবি" এর জন্য একটি নতুন প্রয়োজনীয়তা রয়েছে যার জন্য এটির কাজটি করার জন্য অতিরিক্ত পরিমাণে অর্থাত একটি অতিরিক্ত ইনপুট প্যারামিটার প্রয়োজন।

এটির মতো আমাদের অতিরিক্ত ইনপুট প্যারামিটার সহ একটি ওভারলোডেড ডওওয়ার্ক পদ্ধতি প্রয়োজন ... তবে তারপরে সমস্ত বিদ্যমান কর্মীদের সেই পদ্ধতিটি প্রয়োগ করতে হবে - যা সত্য বলে মনে হয় যে এই শ্রমিকরা সত্যই সেই পদ্ধতির দরকার নেই।

সমন্বয়কারীকে কোন কর্মী ব্যবহার করা হচ্ছে সে সম্পর্কে অবহিত রাখার জন্য এবং এখনও প্রতিটি কর্মীকে তার কাজ করার জন্য প্রয়োজনীয় তথ্যের জন্য অনুমতি দেওয়া হলেও কোনও কর্মী যাতে তার প্রয়োজন হয় না এমন কাজ করতে না পারে সেজন্য আমি কীভাবে এটি রিফ্যাক্টর করতে পারি?

ইতিমধ্যে প্রচুর বিদ্যমান শ্রমিক রয়েছে।

নতুন ওয়ার্কারবি বর্গের প্রয়োজনীয়তা মিটানোর জন্য আমি বিদ্যমান কংক্রিট শ্রমিকদের কোনও পরিবর্তন করতে চাই না।

আমি ভেবেছিলাম সম্ভবত এখানে একটি ডেকোরেটর প্যাটার্ন ভাল হবে তবে আমি কোনও সাজসজ্জনকারী একই পদ্ধতি নয় তবে এর আগে বিভিন্ন পরামিতিগুলির সাথে কোনও জিনিস সাজাইতে দেখিনি ...

কোডের অবস্থা:

public class Coordinator
{
    public string GetWorkerResult(string workerName, int a, List<int> b, string c)
    {
        var workerFactor = new WorkerFactory();
        var worker = workerFactor.GetWorker(workerName);

        if(worker!=null)
            return worker.DoWork(a, b);
        else
            return string.Empty;
    }
}

public class WorkerFactory
{
    public IWorker GetWorker(string workerName)
    {
        switch (workerName)
        {
            case "WorkerA":
                return new ConcreteWorkerA();
            case "WorkerB":
                return new ConcreteWorkerB();
            default:
                return null;
        }
    }
}

public interface IWorker
{
    string DoWork(int a, List<int> b);
}

public class ConcreteWorkerA : IWorker
{
    public string DoWork(int a, List<int> b)
    {
        // does the required work
        return "some A worker result";
    }
}

public class ConcreteWorkerB : IWorker
{
    public string DoWork(int a, List<int> b, string c)
    {
        // does some different work based on the value of 'c'
        return "some B worker result";
    }

    public string DoWork(int a, List<int> b)
    {
        // this method isn't really relevant to WorkerB as it is missing variable 'c'
        return "some B worker result";
    }    
}

IWorkerইন্টারফেসটি কি পুরানো সংস্করণটি তালিকাভুক্ত করেছে, বা এটি যুক্ত পরামিতি সহ নতুন সংস্করণ?
জেমস ফ্যাক্স

আপনার কোড বেসে যে জায়গাগুলি বর্তমানে 2 প্যারামিটার সহ 2W প্যারামিটারগুলির সাথে IWorker ব্যবহার করছে সেগুলিতে কি 3 য় প্যারামিটারটি প্লাগ করতে হবে, বা কেবলমাত্র নতুন কল সাইটগুলি 3 য় প্যারামিটার ব্যবহার করছে?
জেমসফেক্স 1 '11

2
কোনও প্যাটার্ন শপিংয়ের পরিবর্তে, কোনও প্যাটার্ন প্রযোজ্য কিনা তা নির্বিশেষে সামগ্রিক নকশায় মনোযোগ দেওয়ার চেষ্টা করুন । প্রস্তাবিত পড়া: "প্যাটার্নগুলির জন্য কেনাকাটা" টাইপ প্রশ্নগুলি কতটা খারাপ?

1
আপনার কোড অনুসারে, আপনি IWorker উদাহরণটি তৈরি করার আগে প্রয়োজনীয় সমস্ত প্যারামিটারগুলি ইতিমধ্যে জানেন know সুতরাং, আপনার উচিত উচিত এই আর্গুমেন্টগুলি কন্সট্রাক্টরের কাছে পাস করা উচিত ডুওর্ক পদ্ধতিতে নয়। IOW, আপনার ফ্যাক্টরি ক্লাসটি ব্যবহার করুন of উদাহরণটি নির্মাণের বিশদটি গোপন করা কারখানা শ্রেণীর অস্তিত্বের মূল কারণ pretty আপনি যদি এই পদ্ধতির গ্রহণ করেন তবে সমাধানটি তুচ্ছ। এছাড়াও, আপনি যেভাবে এটি সম্পাদন করতে চেষ্টা করছেন তা অর্জন করার চেষ্টা করছেন তা ওও খারাপ। এটি লিসকো সাবস্টিটিউশন নীতি লঙ্ঘন করে।
ডাঙ্ক

1
আমি আপনাকে অন্য স্তর ফিরে যেতে হবে বলে মনে হয়। Coordinatorইতিমধ্যে তার অতিরিক্ত GetWorkerResultক্রিয়াকলাপটির অতিরিক্ত পরামিতিগুলিকে সমন্বিত করতে পরিবর্তন করতে হয়েছিল - এর অর্থ হল যে সলাইডের ওপেন-ক্লোজড-নীতি লঙ্ঘন করা হয়েছে। ফলস্বরূপ, সমস্ত কোড কলিংও Coordinator.GetWorkerResultপরিবর্তন করতে হয়েছিল। সুতরাং যে জায়গাতে আপনি সেই ফাংশনটি বলছেন সেই জায়গার দিকে তাকান: কোন আইওয়ার্কারকে অনুরোধ করবেন তা আপনি কীভাবে সিদ্ধান্ত নেবেন? এটি আরও ভাল সমাধানের দিকে নিয়ে যেতে পারে।
বার্নহার্ড হিলার

উত্তর:


9

আপনাকে আর্গুমেন্টগুলি সাধারণীকরণ করতে হবে যাতে তারা বেস ইন্টারফেস এবং একটি ক্ষেত্র বা বৈশিষ্ট্যগুলির একটি পরিবর্তনশীল সংখ্যার সাথে একক প্যারামিটারে ফিট করে। এর মতো বাছাই করুন:

public interface IArgs
{
    //Can be empty
}

public interface IWorker
{
    string DoWork(IArgs args);
}

public class ConcreteArgsA : IArgs
{
    public int a;
    public List<int> b;
}

public class ConcreteArgsB : IArgs
{
    public int a;
    public List<int> b;
    public string c;
}

public class ConcreteWorkerA : IWorker
{
    public string DoWork(IArgs args)
    {
        var ConcreteArgs = args as ConcreteArgsA;
        if (args == null) throw new ArgumentException();
        return "some A worker result";
    }
}

public class ConcreteWorkerB : IWorker
{
    public string DoWork(IArgs args)
    {
        var ConcreteArgs = args as ConcreteArgsB;
        if (args == null) throw new ArgumentException();
        return "some B worker result";
    }
} 

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

আপনি যদি আর্গুমেন্টগুলির প্রতিটি সম্ভাব্য সংমিশ্রনের জন্য সত্যই কংক্রিট অবজেক্ট তৈরি করতে না চান তবে আপনি তার পরিবর্তে একটি টিপল ব্যবহার করতে পারেন (আমার প্রথম পছন্দ হবে না))

public string GetWorkerResult(string workerName, object args)
{
    var workerFactor = new WorkerFactory();
    var worker = workerFactor.GetWorker(workerName);

    if(worker!=null)
        return worker.DoWork(args);
    else
        return string.Empty;
}

//Sample call
var args = new Tuple<int, List<int>, string>(1234, 
                                             new List<int>(){1,2}, 
                                             "A string");    
GetWorkerResult("MyWorkerName", args);

1
উইন্ডোজ ফর্ম অ্যাপ্লিকেশনগুলি ইভেন্টগুলির সাথে কীভাবে ডিল করে তা এটির মতো। 1 "আরগস" প্যারামিটার এবং একটি "ইভেন্টের উত্স" পরামিতি। সবগুলি "args" EventArgs থেকে subclassed করা হয়: msdn.microsoft.com/en-us/library/... -> আমি বলতে চাই যে এই প্যাটার্ন খুব ভাল কাজ করে। আমি শুধু "টিপল" পরামর্শটি পছন্দ করি না।
মাচাডো

if (args == null) throw new ArgumentException();এখন আইওয়র্ককারের প্রতিটি গ্রাহককে অবশ্যই এর কংক্রিটের ধরণটি জানতে হবে - এবং ইন্টারফেসটি অকেজো: আপনি পাশাপাশি এটি থেকে মুক্তি পেতে পারেন এবং পরিবর্তে কংক্রিটের ধরণগুলি ব্যবহার করতে পারেন। এবং এটি একটি খারাপ ধারণা, তাই না?
বার্নহার্ড হিলার

প্লাগেবল আর্কিটেকচারের কারণে আইওয়ারকার্ক ইন্টারফেসের প্রয়োজন ( WorkerFactory.GetWorkerকেবলমাত্র একটি রিটার্ন টাইপ থাকতে পারে)। এই উদাহরণের আওতার বাইরে থাকাকালীন, আমরা জানি কলার একটি সাথে আসতে সক্ষম workerName; সম্ভবত এটি যথাযথ যুক্তিগুলির সাথেও আসতে পারে।
জন উউ

2

@ ডঙ্কের মন্তব্যের ভিত্তিতে আমি সমাধানটি পুনরায় ইঞ্জিনিয়ার করেছি:

... আপনি ইতিমধ্যে আইওয়ারকার্স উদাহরণটি তৈরি করার আগে প্রয়োজনীয় সমস্ত পরামিতিগুলি জানেন। সুতরাং, আপনার উচিত উচিত এই আর্গুমেন্টগুলি কন্সট্রাক্টরের কাছে পাস করা উচিত ডুওর্ক পদ্ধতিতে নয়। IOW, আপনার ফ্যাক্টরি ক্লাসটি ব্যবহার করুন of উদাহরণটি নির্মাণের বিশদটি গোপন করা কারখানা শ্রেণীর অস্তিত্বের মূল কারণ pretty

সুতরাং আমি আইওয়র্ককার তৈরির জন্য প্রয়োজনীয় সমস্ত সম্ভাব্য যুক্তিগুলি আইওয়ারোরফ্যাক্টরি.গেট ওয়ার্কার পদ্ধতিতে স্থানান্তরিত করেছি এবং তারপরে প্রতিটি কর্মীর ইতিমধ্যে যা প্রয়োজন তা রয়েছে এবং সমন্বয়কারী কেবল কর্মীকে কল করতে পারেন o ডু ওয়ার্ক ();

    public interface IWorkerFactory
    {
        IWorker GetWorker(string workerName, int a, List<int> b, string c);
    }

    public class WorkerFactory : IWorkerFactory
    {
        public IWorker GetWorker(string workerName, int a, List<int> b, string c)
        {
            switch (workerName)
            {
                case "WorkerA":
                    return new ConcreteWorkerA(a, b);
                case "WorkerB":
                    return new ConcreteWorkerB(a, b, c);
                default:
                    return null;
            }
        }
    }

    public class Coordinator
    {
        private readonly IWorkerFactory _workerFactory;

        public Coordinator(IWorkerFactory workerFactory)
        {
            _workerFactory = workerFactory;
        }

        // Adding 'c' breaks Open/Closed principal for the Coordinator and WorkerFactory; but this has to happen somewhere...
        public string GetWorkerResult(string workerName, int a, List<int> b, string c)
        {
            var worker = _workerFactory.GetWorker(workerName, a, b, c);

            if (worker != null)
                return worker.DoWork();
            else
                return string.Empty;
        }
    }

    public interface IWorker
    {
        string DoWork();
    }

    public class ConcreteWorkerA : IWorker
    {
        private readonly int _a;
        private readonly List<int> _b;

        public ConcreteWorkerA(int a, List<int> b)
        {
            _a = a;
            _b = b;
        }

        public string DoWork()
        {
            // does the required work based on 'a' and 'b'
            return "some A worker result";
        }
    }

    public class ConcreteWorkerB : IWorker
    {
        private readonly int _a;
        private readonly List<int> _b;
        private readonly string _c;

        public ConcreteWorkerB(int a, List<int> b, string c)
        {
            _a = a;
            _b = b;
            _c = c;
        }

        public string DoWork()
        {
            // does some different work based on the value of 'a', 'b' and 'c'
            return "some B worker result";
        }
    }

1
আপনার কাছে একটি ফ্যাক্টরি পদ্ধতি রয়েছে যা 3 টি পরামিতি পায় যদিও 3 টি সমস্ত পরিস্থিতিতে ব্যবহার করা হয় না। আপনার যদি এমন একটি অবজেক্ট সি থাকে যা আরও বেশি পরামিতিগুলির প্রয়োজন হয় তবে আপনি কী করবেন? আপনি কি তাদের পদ্ধতিতে স্বাক্ষরে যুক্ত করবেন? এই সমাধানটি প্রসারণযোগ্য এবং অসুস্থ পরামর্শ দেওয়া আইএমও নয়
এমরোফিস

3
আমার যদি এমন একটি নতুন কংক্রিট ওয়ার্কারসিসি দরকার হয় যার আরও আর্গুমেন্ট দরকার, তবে হ্যাঁ, সেগুলি getWorker পদ্ধতিতে যুক্ত করা হবে। হ্যাঁ, ফ্যাক্টরিটি ওপেন / ক্লোজড অধ্যক্ষের সাথে সামঞ্জস্য করে না - তবে কোথাও কোথাও কিছু এমন হতে হবে এবং আমার মতে ফ্যাক্টরিটি সেরা বিকল্প ছিল। আমার পরামর্শটি হ'ল: এটির পক্ষে পরামর্শ দেওয়া ঠিক নয়, আপনি বিকল্প সমাধান পোস্ট করে সম্প্রদায়কে সহায়তা করবেন।
জেটেক

1

আমি বেশ কয়েকটি বিষয়ের একটি পরামর্শ দেব।

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

অন্য বিকল্পগুলির বিরুদ্ধে আমি সুপারিশ করব, কারণ এটি এনক্যাপসুলেশনটি ভেঙে দেয় এবং এটি সাধারণত খারাপ ওওপি হয়। এর জন্য এটিও প্রয়োজন যে আপনি কমপক্ষে সমস্ত কলসাইটগুলি সংশোধন করতে পারেন ConcreteWorkerB। আপনি একটি শ্রেণি তৈরি করতে পারেন যা IWorkerইন্টারফেস প্রয়োগ করে তবে DoWorkঅতিরিক্ত প্যারামিটার সহ একটি পদ্ধতিও রয়েছে। তারপর আপনার callsites নিক্ষেপ করার চেষ্টা IWorkerসঙ্গে var workerB = myIWorker as ConcreteWorkerB;এবং তারপর তিন পরামিতি ব্যবহার DoWorkকংক্রিট ধরনের উপর। আবার এটি একটি খারাপ ধারণা, তবে এটি এমন কিছু যা আপনি করতে পারেন।


0

@ জেটেক, আপনি কি paramsযুক্তিটি ব্যবহারের বিষয়টি বিবেচনা করেছেন ? এটি প্যারামিটারগুলির একটি পরিবর্তনশীল পরিমাণটি পাস করার অনুমতি দেয়।

https://msdn.microsoft.com/en-us/library/w5zay9db(v=vs.71).aspx


প্যারাম কীওয়ার্ডটি বোধগম্য হতে পারে যদি ডো ওয়ার্ক পদ্ধতিটি প্রতিটি যুক্তির সাথে একই জিনিস করে এবং যদি প্রতিটি যুক্তি একই ধরণের হয়। অন্যথায়, ডোওয়ার্ক পদ্ধতিতে পরীক্ষা করা দরকার যে প্যারাম অ্যারেতে প্রতিটি যুক্তি সঠিক ধরণের ছিল - তবে আমরা বলতে পারি যে সেখানে আমাদের দুটি স্ট্রিং রয়েছে এবং প্রত্যেকটি পৃথক উদ্দেশ্যে ব্যবহৃত হয়েছিল, কীভাবে ডউওর্ক নিশ্চিত করতে পারে যে এটির সঠিক রয়েছে এক ... এটি অ্যারে অবস্থানের উপর ভিত্তি করে ধরে নিতে হবে। সব আমার পছন্দ মত Allিলা। আমি @ জনউ এর সমাধান আরও কঠোর মনে করি।
JTech
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.