আচরণগত হিসাবে ইন্টারফেস সহ বিমূর্ত বেস শ্রেণি?


14

আমার সি # প্রকল্পের জন্য আমার একটি শ্রেণি শ্রেণিবিন্যাসের নকশা করা দরকার। মূলত, ক্লাসের ক্রিয়াকলাপগুলি উইনফর্মস ক্লাসগুলির সাথে সমান তাই তাই উদাহরণস্বরূপ উইনফর্মস টুলকিটটি নেওয়া যাক। (তবে আমি উইনফর্মস বা ডাব্লুপিএফ ব্যবহার করতে পারি না))

কিছু প্রাথমিক বৈশিষ্ট্য এবং কার্যকারিতা রয়েছে যা প্রতিটি শ্রেণীর সরবরাহ করা প্রয়োজন। মাত্রা, অবস্থান, রঙ, দৃশ্যমানতা (সত্য / মিথ্যা), অঙ্কন পদ্ধতি ইত্যাদি

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

কোডটি এর মতো দেখাচ্ছে:

abstract class Control
{
    public int Width { get; set; }

    public int Height { get; set; }

    public int BackColor { get; set; }

    public int X { get; set; }

    public int Y { get; set; }

    public int BorderWidth { get; set; }

    public int BorderColor { get; set; }

    public bool Visible { get; set; }

    public Rectangle ClipRectange { get; protected set; }

    abstract public void Draw();
}

কিছু নিয়ন্ত্রণে অন্যান্য নিয়ন্ত্রণ থাকতে পারে, কিছু কেবলমাত্র (শিশু হিসাবে) থাকতে পারে তাই আমি এই কার্যকারিতাটির জন্য দুটি ইন্টারফেস তৈরি করার কথা ভাবছি:

interface IChild
{
    IContainer Parent { get; set; }
}

internal interface IContainer
{
    void AddChild<T>(T child) where T : IChild;
    void RemoveChild<T>(T child) where T : IChild;
    IChild GetChild(int index);
}

উইনফোর্ডস প্রদর্শন পাঠ্য নিয়ন্ত্রণ করে যাতে এটি ইন্টারফেসেও যায়:

interface ITextHolder
{
    string Text { get; set; }
    int TextPositionX { get; set; }
    int TextPositionY { get; set; }
    int TextWidth { get; }
    int TextHeight { get; }

    void DrawText();
}

কিছু নিয়ন্ত্রণগুলি তাদের পিতামাতার নিয়ন্ত্রণের মধ্যে ডক করা যায় তাই:

enum Docking
{ 
    None, Left, Right, Top, Bottom, Fill
}

interface IDockable
{
    Docking Dock { get; set; }
}

... এবং এখন কয়েকটি কংক্রিট শ্রেণি তৈরি করা যাক:

class Panel : Control, IDockable, IContainer, IChild {}
class Label : Control, IDockable, IChild, ITextHolder {}
class Button : Control, IChild, ITextHolder, IDockable {}
class Window : Control, IContainer, IDockable {}

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

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

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

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

আমার মনে হয় এটিকে "কৌশল" প্যাটার্ন বলা হয় এবং যদিও এই বিষয়টিতে লক্ষ লক্ষ প্রশ্ন ও উত্তর রয়েছে, আমি আপনাকে এই নকশার জন্য আমি কী বিবেচনা করছি এবং আপনি কী ত্রুটিগুলি নিয়ে ভাবতে পারেন সে সম্পর্কে আপনার মতামত জানতে চাই আমার পদ্ধতির

আমার যোগ করা উচিত যে প্রায় 100% সম্ভাবনা রয়েছে যা ভবিষ্যতের প্রয়োজনীয়তাগুলি নতুন ক্লাস এবং নতুন কার্যকারিতার জন্য কল করবে।


কেন না System.ComponentModel.Componentবা System.Windows.Forms.Controlঅন্য বিদ্যমান বেস ক্লাসগুলির মধ্যে থেকে উত্তরাধিকারী হয় ? আপনার নিজের নিয়ন্ত্রণ স্তরক্রম তৈরি করতে এবং স্ক্র্যাচ থেকে এই সমস্ত ফাংশনগুলি আবার সংজ্ঞায়িত করার প্রয়োজন কেন?
কোডি গ্রে

3
IChildএকটি ভয়ঙ্কর নাম মত মনে হচ্ছে।
রায়নস

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

2
আপনি উইনফর্মস বা ডাব্লুপিএফ অ্যাসেমব্লিগুলি ব্যবহার করতে পারবেন না তা বলার মতো কোনও ধারণা নেই, তবুও আপনি যে কাস্টম নিয়ন্ত্রণ কাঠামো তৈরি করেছিলেন তা আপনি ব্যবহার করতে সক্ষম হবেন। চাকাটি পুনরায় উদ্ভাবনের এটি একটি গুরুতর ঘটনা, এবং কোন সম্ভাব্য উদ্দেশ্য নিয়ে আমি কল্পনাও করতে পারি না। তবে যদি আপনার অবশ্যই আবশ্যক, তবে কেন কেবল উইনফোর্ডস নিয়ন্ত্রণগুলির উদাহরণ অনুসরণ করবেন না ? এটি এই প্রশ্নটিকে বেশ অচল করে দেয়।
কোডি গ্রে

1
@ চিত্রক্লোকলে এ কারণেই এটি একটি মন্তব্য :) যদি আমি দিতে সত্যিকারের দরকারী প্রতিক্রিয়া থাকি তবে আমি আপনার প্রশ্নের উত্তর জানতাম। এটি এখনও একটি ভয়াবহ নাম;)
রায়নস

উত্তর:


5

[1] আপনার সম্পত্তিগুলিতে ভার্চুয়াল "গেটার্স" এবং "সেটটার" যুক্ত করুন, আমাকে অন্য একটি নিয়ন্ত্রণ গ্রন্থাগার হ্যাক করতে হয়েছিল, কারণ আমার এই বৈশিষ্ট্যটি প্রয়োজন:

abstract class Control
{
    // internal fields for properties
    protected int _Width;
    protected int _Height;
    protected int _BackColor;
    protected int _X;
    protected int _Y;
    protected bool Visible;

    protected int BorderWidth;
    protected int BorderColor;


    // getters & setters virtual !!!

    public virtual int getWidth(...) { ... }
    public virtual void setWidth(...) { ... }

    public virtual int getHeight(...) { ... }
    public virtual void setHeight(...) { ... }

    public virtual int getBackColor(...) { ... }
    public virtual void setBackColor(...) { ... }

    public virtual int getX(...) { ... }
    public virtual void setX(...) { ... }

    public virtual int getY(...) { ... }
    public virtual void setY(...) { ... }

    public virtual int getBorderWidth(...) { ... }
    public virtual void setBorderWidth(...) { ... }

    public virtual int getBorderColor(...) { ... }
    public virtual void setBorderColor(...) { ... }

    public virtual bool getVisible(...) { ... }
    public virtual void setVisible(...) { ... }

    // properties WITH virtual getters & setters

    public int Width { get getWidth(); set setWidth(value); }

    public int Height { get getHeight(); set setHeight(value); }

    public int BackColor { get getBackColor(); set setBackColor(value); }

    public int X { get getX(); set setX(value); }

    public int Y { get getY(); set setY(value); }

    public int BorderWidth { get getBorderWidth(); set setBorderWidth(value); }

    public int BorderColor { get getBorderColor(); set setBorderColor(value); }

    public bool Visible { get getVisible(); set setVisible(value); }

    // other methods

    public Rectangle ClipRectange { get; protected set; }   
    abstract public void Draw();
} // class Control

/* concrete */ class MyControl: Control
{
    public override bool getVisible(...) { ... }
    public override void setVisible(...) { ... }
} // class MyControl: Control

আমি জানি এই পরামর্শটি আরও "ভার্বোজ" বা জটিল, তবে, এটি বাস্তব বিশ্বে খুব কার্যকর।

[2] একটি "ইসনেবল" সম্পত্তি যুক্ত করুন, "ইসরেডঅনলি" দিয়ে বিভ্রান্ত করবেন না:

abstract class Control
{
    // internal fields for properties
    protected bool _IsEnabled;

    public virtual bool getIsEnabled(...) { ... }
    public virtual void setIsEnabled(...) { ... }

    public bool IsEnabled{ get getIsEnabled(); set setIsEnabled(value); }
} // class Control

মানে আপনাকে আপনার নিয়ন্ত্রণ দেখাতে হতে পারে, তবে কোনও তথ্য প্রদর্শন করবেন না।

[3] একটি "ইসরেডঅনলি" সম্পত্তি যুক্ত করুন, "ইসইনেবল" দিয়ে বিভ্রান্ত করবেন না:

abstract class Control
{
    // internal fields for properties
    protected bool _IsReadOnly;

    public virtual bool getIsReadOnly(...) { ... }
    public virtual void setIsReadOnly(...) { ... }

    public bool IsReadOnly{ get getIsReadOnly(); set setIsReadOnly(value); }
} // class Control

এর অর্থ নিয়ন্ত্রণটি তথ্য প্রদর্শন করতে পারে তবে ব্যবহারকারীর দ্বারা পরিবর্তন করা যায় না।


যদিও আমি বেস ক্লাসে এই সমস্ত ভার্চুয়াল পদ্ধতি পছন্দ করি না আমি তাদের নকশা সম্পর্কে আমার চিন্তায় দ্বিতীয় সুযোগ দেব। এবং আপনি আমাকে স্মরণ করিয়ে দিয়েছিলেন যে আমার আসলেই ইস্রাডঅনলির সম্পত্তি দরকার :)
grapkulec

@grapkulec এটা যেহেতু তার বেস বর্গ, আপনার নির্দিষ্ট করা হবে যে উদ্ভূত শ্রেণীর ঐ বৈশিষ্ট্য আছে হবে, কিন্তু, যে পদ্ধতি নিয়ন্ত্রণ আচরণ প্রতিটি বর্গ purpouse ;-) উপর পরিবর্তন হতে পারে
umlcat

মিমকি, আমি আপনার বক্তব্যটি দেখতে পেয়েছি এবং উত্তর দেওয়ার জন্য সময় দেওয়ার জন্য আপনাকে ধন্যবাদ জানাই
18-28 এ গ্রাপক্লেকেল

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

3

সুন্দর প্রশ্ন! প্রথম যে বিষয়টি আমি লক্ষ্য করেছি তা হল যে ড্র পদ্ধতির কোনও পরামিতি নেই, এটি কোথায় আঁকবে? আমি মনে করি এটির কিছু পরামিতি বা গ্রাফিক্স বস্তু প্যারামিটার হিসাবে পাওয়া উচিত (অবশ্যই ইন্টারফেস হিসাবে)।

আরও একটি বিষয় যা আমি অদ্ভুত মনে করি তা হ'ল আইকন্টেইনার ইন্টারফেস। এটা আছে GetChildযে পদ্ধতি আয় একটি একক সন্তান ও কোন প্যারামিটার আছে - হয়তো এটা একটা সংগ্রহ ফেরত পাঠাবেন অথবা আপনি যদি একটি ইন্টারফেসে অঙ্কন পদ্ধতি সরানো তাহলে এই ইন্টারফেস বাস্তবায়ন এবং ড্র পদ্ধতি এটি প্রকাশক ছাড়া অভ্যন্তরীণ শিশুদের সংগ্রহ আহরণ করতে পারে হতে পারে ।

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

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

পোস্টটি বরং দীর্ঘতর হচ্ছে তাই আপনি যদি সেই ধারণাটি আকর্ষণীয় মনে করেন এবং আমাকে কিছু উদাহরণ বা আরও ব্যাখ্যা দিতে পারি তবে আমাকে জানান।


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

@ গ্র্যাপক্লেক আপনাকে স্বাগতম! প্যারামগুলি সম্পর্কে - হ্যাঁ, ঠিক আছে, আমি নিশ্চিত হয়েছি যে আমি আপনার ইনটেনশনগুলি সঠিকভাবে বুঝতে পেরেছি। আমি আপনি মতামত পছন্দ করে খুশি। শুভকামনা!

2

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

আমি প্রকৃতপক্ষে এমন একটি পদ্ধতি ব্যবহার করেছি (আমার রেন্ডারিং ইঞ্জিনে) যেখানে প্রতিটি ইন্টারফেস গ্রাহক সাবসিস্টেমের প্রত্যাশিত আচরণটিকে সংজ্ঞায়িত করে। উদাহরণস্বরূপ, IUpdateable, ICollidable, IRenderable, ILoadable, ILoader এবং আরও অনেক কিছু। স্পষ্টতার জন্য, আমি এই "আচরণ" প্রত্যেককে আলাদা আলাদা আংশিক শ্রেণিতে যেমন "এন্টি.আই.ইউপিডেটেবল.সিএস", "সত্তা.আইআরএনডিয়ারেবল সি।" - তে আলাদা করে দিয়েছিলাম এবং ক্ষেত্রগুলি এবং পদ্ধতিগুলি যতটা সম্ভব স্বাধীন রাখতে চেষ্টা করেছি।

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

ডিজাইনের এই পদ্ধতিটি সম্পর্কে আমি একটি পর্যবেক্ষণ করেছি: আপনি যদি কখনও নিজেকে গুটি কয়েক পদ্ধতির চেয়ে ইন্টারফেসের সংজ্ঞা দিতে দেখেন তবে আপনি সম্ভবত কোনও আচরণ বাস্তবায়ন করছেন না।


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