কমান্ড প্যাটার্ন ডিজাইন


11

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

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

ব্যবহারের ক্ষেত্রে উদাহরণ: ধরা যাক কমান্ডবিতে ব্যবহারকারীর নাম প্রয়োজন যা কমান্ডএ দ্বারা সেট করা আছে । কমান্ডএ কী কী ব্যবহারকারীনামফর্মকম্যান্ডবি = জনকে সেট করতে হবে ? অথবা তাদের একটি সাধারণ ব্যবহারকারীর নাম = জন কী-মানটি ভাগ করা উচিত ? যদি ইউজারনেম তৃতীয় কমান্ড ব্যবহার করে তবে কী হবে?

আমি কীভাবে এই নকশাটি উন্নত করতে পারি? ধন্যবাদ!

class DIParameters {
public:
   /**
    * Parameter setter.
    */
    virtual void setParameter(std::string key, std::string value) = 0;
    /**
    * Parameter getter.
    */
    virtual std::string getParameter(std::string key) const = 0;

    virtual ~DIParameters() = 0;
};

class DIOperation {
public:
    /**
     * Visit before performing execution.
     */
    virtual void visitBefore(DIParameters& visitee) = 0;
    /**
     * Perform.
     */
    virtual int perform() = 0;
    /**
     * Visit after performing execution.
     */
    virtual void visitAfter(DIParameters& visitee) = 0;

    virtual ~DIOperation() = 0;
};

3
বৈশিষ্ট্য (নাম হিসাবে) সেট করতে কমান্ড ব্যবহার করে আমার ভাগ্য কখনও হয় নি। এটি খুব নির্ভরশীল হতে শুরু করে। যদি আপনার সেটিং বৈশিষ্ট্যগুলি কোনও ইভেন্ট আর্কিটেকচার বা একটি পর্যবেক্ষক প্যাটার্ন ব্যবহার করার চেষ্টা করে।
অহেনডারসন

1
1. কেন পৃথক দর্শকের মাধ্যমে পরামিতিগুলি পাস করবেন? পারফরম্যান্সের যুক্তি হিসাবে একটি প্রসঙ্গ পাস করার সাথে কী সমস্যা? 2. প্রসঙ্গটি কমান্ডের 'সাধারণ' অংশের জন্য (যেমন বর্তমান সেশন / ডকুমেন্ট)। সমস্ত অপারেশন-নির্দিষ্ট পরামিতি অপারেশনের কনস্ট্রাক্টরের মাধ্যমে আরও ভালভাবে পাস করা হয়।
ক্রিস ভ্যান বায়েল

@ ক্রিসভ্যানবেল এটিই বিভ্রান্তিকর অংশ যা আমি পরিবর্তনের চেষ্টা করছি। আমি এটি দর্শকের হিসাবে দিয়ে যাচ্ছি যখন এটি আসলে প্রসঙ্গ হয় ...
আন্ড্রেয়া রিচার্ডি

@ এহেনডারসন আপনি কি আমার আদেশের মধ্যে ঘটনাগুলির অর্থ সঠিক? আপনি কি কী কী-মানগুলি সেখানে রাখবেন (পার্সেলের সাথে অ্যান্ড্রয়েডের মতো)? এটি কী অর্থে একই হবে যে কমান্ডবাকে কী-মানযুক্ত জোড়গুলি কমান্ডবি গ্রহণ করে একটি ইভেন্ট তৈরি করা উচিত?
আন্ড্রেয়া রিচিয়ার্ডি

উত্তর:


2

আপনার কমান্ড প্যারামিটারগুলির পরিবর্তন সম্পর্কে আমি কিছুটা উদ্বিগ্ন। নিয়মিত পরামিতি পরিবর্তন করে একটি কমান্ড তৈরি করা কি সত্যিই প্রয়োজনীয়?

আপনার পদ্ধতির সাথে সমস্যাগুলি:

আপনি কি চান যে অন্য থ্রেড / কমান্ডগুলি performচলমান অবস্থায় আপনার পরামিতিগুলি পরিবর্তন করতে চান ?

আপনি কি চান visitBeforeএবং visitAfterএকই Commandঅবজেক্টকে বিভিন্ন DIParameterঅবজেক্টের সাথে ডাকা হবে ?

আপনি কি চান যে কেউ আপনার কমান্ডগুলিতে প্যারামিটারগুলি খাওয়াতে পারে, যাতে আদেশগুলি সম্পর্কে কোনও ধারণা নেই?

এর কিছুই আপনার বর্তমান ডিজাইন দ্বারা নিষিদ্ধ নয়। যদিও একটি জেনেরিক কী-মানের প্যারামিটার ধারণাগুলির মাঝে মাঝে এর গুণাবলী থাকে, আমি জেনেরিক কমান্ড শ্রেণীর সাথে এটি পছন্দ করি না।

পরিণতির উদাহরণ:

আপনার Commandশ্রেণীর একটি দৃ concrete় উপলব্ধি বিবেচনা করুন - এরকম কিছু CreateUserCommand। এখন স্পষ্টতই, আপনি যখন নতুন ব্যবহারকারী তৈরি করার অনুরোধ করবেন তখন কমান্ডটির জন্য সেই ব্যবহারকারীর একটি নাম প্রয়োজন হবে। প্রদত্ত যে আমি CreateUserCommandএবং DIParametersক্লাসগুলি জানি , আমার কোন পরামিতিটি সেট করা উচিত?

আমি userNameপ্যারামিটার সেট করতে পারলাম , বা username.. আপনি কি পরামিতিগুলির কেসটিকে সংবেদনশীলতার সাথে আচরণ করবেন? আমি সত্যিই জানতাম না .. ওহ অপেক্ষা করুন .. সম্ভবত এটি ঠিক name?

আপনি যেমন জেনেরিক কী-মান ম্যাপিং থেকে যে স্বাধীনতা অর্জন করতে পারেন তা বোঝা যায় যে আপনার ক্লাসগুলি এমন কেউ হিসাবে প্রয়োগ করা হয়নি যা বাস্তবায়ন করেনি অযৌক্তিকভাবে কঠিন। সেই আদেশটি দ্বারা কোন কীগুলি সমর্থিত তা অন্যকে জানানোর জন্য আপনার কমপক্ষে আপনার কমান্ডগুলির জন্য কিছু ধ্রুবক সরবরাহ করতে হবে।

সম্ভাব্য বিভিন্ন ডিজাইনের পন্থা:

  • Parameterঅপরিবর্তনীয় পরামিতি: আপনার দৃষ্টান্তগুলিকে অপরিবর্তনীয় করে তোলার মাধ্যমে আপনি অবাধে তাদের বিভিন্ন কমান্ডের মধ্যে পুনরায় ব্যবহার করতে পারেন।
  • নির্দিষ্ট প্যারামিটার ক্লাস: UserParameterএমন কোনও শ্রেণি দেওয়া হয়েছে যাতে একটি ব্যবহারকারীকে জড়িত কমান্ডগুলির জন্য আমার ঠিক প্যারামিটার থাকতে হবে, এই API এর সাথে কাজ করা আরও সহজ হবে। প্যারামিটারগুলিতে আপনার এখনও উত্তরাধিকার থাকতে পারে তবে কমান্ড ক্লাসগুলিকে স্বেচ্ছাচারিত প্যারামিটারগুলি গ্রহণ করা আর কোনও অর্থহীন হবে না - অবশ্যই পক্ষের প্রান্তে এটির অর্থ হ'ল এপিআই ব্যবহারকারীরা জানেন যে কোন পরামিতিগুলি হুবহু প্রয়োজনীয়।
  • প্রসঙ্গে প্রতিটি কমান্ড উদাহরণ: আপনার যদি আপনার কমান্ডগুলির মতো জিনিস থাকতে হয় visitBeforeএবং visitAfterবিভিন্ন পরামিতিগুলির সাথে সেগুলি পুনরায় ব্যবহার করা হয় তবে আপনি পৃথক পৃথক পরামিতিগুলির সাথে কল করার সমস্যাটি উন্মুক্ত করতে পারেন। যদি একাধিক পদ্ধতি কলগুলিতে প্যারামিটারগুলি একই হতে পারে তবে আপনাকে সেগুলি কমান্ডের মধ্যে এমনভাবে আবদ্ধ করতে হবে যাতে তারা কলগুলির মধ্যে থাকা অন্যান্য পরামিতিগুলির জন্য স্যুইচ আউট করতে পারে না।

হ্যাঁ, আমি ভিজিটর আগে এবং ভিজিটএফ থেকে মুক্তি পেয়েছি। আমি মূলত পারফর্ম পদ্ধতিতে আমার ডিপারামিটার ইন্টারফেসটি পাস করছি। অনাকাঙ্ক্ষিত ডিআইপিআরএমটার্স উদাহরণগুলির সাথে সমস্যাটি সর্বদা থাকবে, কারণ আমি ইন্টারফেসটি পাস করার নমনীয়তাটি বেছে নিয়েছি। আমি সাবক্লাস করতে সক্ষম হয়েছি এবং ডিআইপিআরমিটার শিশুদের একবার পূর্ণ হয়ে গেলে তারা অপরিবর্তনীয় করে তোলার ধারণাটি আমার পছন্দ হয় like যাইহোক, একটি "কেন্দ্রীয় কর্তৃপক্ষ" এখনও কমান্ডের সঠিক DIParameter পাস করা প্রয়োজন। সম্ভবত এই কারণেই আমি একটি ভিজিটর ধাঁচ বাস্তবায়ন শুরু করেছি..আমি কোনওভাবে নিয়ন্ত্রণের বিপরীতমুখীতা থাকতে চাই ...
Andrea Richiardi

0

নকশা নীতিগুলি সম্পর্কে যা সুন্দর তা তাড়াতাড়ি বা পরে, তারা একে অপরের সাথে বিরোধ করে।

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

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


1
আপনি এখানে কোন নীতিগুলি বিরোধী মনে করেন?
জিমি হোফা

কেবল স্পষ্ট করে বলার জন্য, আমার সমস্যাটি প্রসঙ্গ বা দর্শনার্থী বিন্যাসের মধ্যে পছন্দ করে না। আমি মূলত ভিজিটর নামক একটি প্রাসঙ্গিক প্যাটার্ন ব্যবহার করছি :)
আন্দ্রে রিচার্ডি

ঠিক আছে, আমি সম্ভবত আপনার সঠিক প্রশ্ন / সমস্যাটি ভুল বুঝেছি।
মার্টিন

0

ধরে নেওয়া যাক আপনার একটি কমান্ড ইন্টারফেস রয়েছে:

class Command {
public:
    void execute() = 0;
};

এবং একটি বিষয়:

class Subject {
    std::string name;
public:
    void setName(const std::string& name) {this->name = name;}
}

আপনার যা প্রয়োজন তা হ'ল:

class NameObserver {
public:
    void update(const std::string& name) = 0;
};

class Subject {
    NameObserver& o;
    std::string name;
private:
    void setName(const std::string& name) {
        this->name = name;
        o.update(name);
    }
};

class CommandB: public Command, public NameObserver {
    std::string name;
public:
    void execute();
    void update(const std::string& name) {
        this->name = name;
        execute();
    }
};

NameObserver& oকমান্ডবি রেফারেন্স হিসাবে সেট করুন । এখন যখনই কমান্ডএ সাবজেক্টের নাম পরিবর্তন করে কমান্ডবি সঠিক তথ্য দিয়ে কার্যকর করতে পারে। নামটি যদি আরও কমান্ড দ্বারা ব্যবহৃত হয় তবে astd::list<NameObserver>


উত্তরের জন্য ধন্যবাদ. এই নকশার ইমোর সমস্যা হ'ল আমাদের প্রতিটি প্যারামিটারে একটি সেটার + নেমসবার্সার দরকার। আমি একটি ডিআইপিআরমিটারগুলি (প্রসঙ্গে) উদাহরণটি পাস করতে এবং বিজ্ঞপ্তি জানাতে পারি, তবে আবার আমি সম্ভবত যে কমান্ডএকে কমান্ডবি'র সাথে সংযুক্ত করছি, তা সম্ভবত সমাধান করব না, যার অর্থ কমান্ডএকে একটি মূল-মূল্য রাখতে হবে যা কেবল কমান্ডবকে জানা উচিত ... আমি যা চেষ্টা করেছিলাম তা ছিল একটি বাহ্যিক সত্তা (প্যারামিটারহ্যান্ডলার) যা কেবলমাত্র কোন কমান্ডের জন্য কোন প্যারামিটারের প্রয়োজন হয় এবং সেই অনুযায়ী ডিআইপিআরমিটার উদাহরণস্বরূপ সেট করে / পায় সেটাই জানা যায়।
আন্ড্রেয়া রিচিয়ার্ডি

@ কেপ "এই নকশার ইমোতে সমস্যাটি হ'ল আমাদের প্রতিটি প্যারামিটারে একটি সেটার + নেমসবার্সার প্রয়োজন" - এই প্রসঙ্গে প্যারামিটারটি আমার জন্য কিছুটা বিভ্রান্তিকর, আমি ভাবছি আপনি ক্ষেত্রটি বোঝাচ্ছেন। কোন ক্ষেত্রে আপনার ইতিমধ্যে পরিবর্তিত প্রতিটি ক্ষেত্রের জন্য একটি সেটার থাকা উচিত। আপনার উদাহরণ থেকে মনে হচ্ছে কোমেন্ডা সাবজেক্টের নাম পরিবর্তন করে। এটি একটি সেটারের মাধ্যমে ক্ষেত্রটি পরিবর্তন করা উচিত। দ্রষ্টব্য: আপনার প্রতি ক্ষেত্রের জন্য কোনও পর্যবেক্ষকের প্রয়োজন নেই, কেবল একজন সরকারী এবং সমস্ত পর্যবেক্ষকের কাছে অবজেক্টটি প্রেরণ করুন।
এহেনডারসন

0

প্রোগ্রামারগুলিতে এটি পরিচালনা করার সঠিক উপায় কিনা আমি জানি না (যার ক্ষেত্রে আমি ক্ষমাপ্রার্থী), তবে, এখানে সমস্ত উত্তর যাচাই করার পরে (বিশেষত ফ্র্যাঙ্কের বিশেষত)। আমি আমার কোডটি এভাবে রিফ্যাক্ট করেছি:

  • ড্রপড ডিআইপিআরমিটারস। DIOperation এর ইনপুট (অপরিবর্তনীয়) হিসাবে আমার পৃথক (জেনেরিক) অবজেক্ট থাকবে। উদাহরণ:
ক্লাস সম্পর্কিতঅবজেক্টট্রিপলেট {
ব্যক্তিগত:
    স্টাড :: স্ট্রিং কনস্টেট মি_স প্রাইমারিওজেক্টআইডি;
    std :: স্ট্রিং কনস্টেট m_sSecondaryObjectId;
    std :: স্ট্রিং কনস্টেট m_sRelationObjectId;

    সম্পর্কিতঅজেক্টট্রিপলেট এবং অপারেটর = (সম্পর্কিতঅবজেক্টট্রিপলেট অন্যান্য);

প্রকাশ্য:
    সম্পর্কিতঅবজেক্টট্রিপলেট (স্ট্যান্ডিং :: স্ট্রিং কনস্ট্যান্ড & এসপ্রিমিওজেক্টআইডি,
                         স্ট্যান্ড :: স্ট্রিং কনস্ট এবং সেকেন্ডারিঅবজেক্টআইডি,
                         স্টাড :: স্ট্রিং কনস্ট্যান্ড & এসরেলেশনবজেক্টআইডি);

    সম্পর্কিতঅবজেক্টট্রিপলেট (সম্পর্কিতঅজেক্টট্রিপলেট কনস্ট্যান্ড এবং অন্যান্য);


    স্টাড :: স্ট্রিং কনস্ট & getPrimaryObjectId () কনস্ট;
    স্টাড :: স্ট্রিং কনস্ট এবং getSecondaryObjectId () কনস্ট;
    স্টাড :: স্ট্রিং কনস্ট & getRelationObjectId () কনস্ট;

    ~ RelatedObjectTriplet ();
};
  • নতুন DIOperation ক্লাস (উদাহরণস্বরূপ) হিসাবে সংজ্ঞায়িত:
টেমপ্লেট <ক্লাস টি = অকার্যকর> 
ক্লাস ডিআইওএপরেশন {
প্রকাশ্য:
    ভার্চুয়াল ইন পারফর্ম () = 0;

    ভার্চুয়াল টি getResult () = 0;

    ভার্চুয়াল ~ DIOperation () = 0;
};

ক্লাস ক্রিয়েটরিলেশন: পাবলিক ডিআইওএপরেশন <রিলেটেডঅবজেক্ট ট্রিপলেট>
ব্যক্তিগত:
    স্ট্যাটিক স্টাড :: স্ট্রিং কনস্ট টাইপ;

    // প্যারাম (অপরিবর্তনীয়)
    সম্পর্কিতঅজেক্টট্রিপলেট কনট m_sParams;

    // গোপন
    ক্রিয়েটরিলেশন ও অপারেটর = (ক্রিয়েটরিলেশন কনস্ট এবং উত্স);
    ক্রিয়েটরিলেশন (ক্রিয়েটরিলেশন কনস্ট এবং উত্স);

    // অভ্যন্তরীণ
    স্টাড :: স্ট্রিং এম_এস নিউ রিলেশনআইডি;

প্রকাশ্য:
    ক্রিয়েটরিলেশন (সম্পর্কিতঅবজেক্টট্রিপলেট কনস্ট্যান্ড এবং প্যারাম);

    int পারফরম্যান্স ();

    সম্পর্কিতঅজেক্টট্রিপলেট getSesult ();

    ~ CreateRelation ();
};
  • এটি এর মতো ব্যবহার করা যেতে পারে:
সম্পর্কিতঅবজেক্টট্রিপলেট ট্রিপলেট ("33333", "55555", "77777");
ক্রিয়েটরিলেশন ক্রেইনরেল (ট্রিপলেট);
createRel.perform ();
কনট রিলেটেডঅবজেক্টট্রিপলেট রেজ = ক্রিয়েল.জেটআরসাল্ট ();

সহায়তার জন্য ধন্যবাদ এবং আমি আশা করি আমি এখানে ভুল করি নি :)

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