" एक पासवर्ड रीसेट कर सकते हैं " के इस विशिष्ट उदाहरण के लिए , मैं अनुशंसा करूँगा कि मैं इनहेरिटेंस (इस मामले में, इंटरफ़ेस / अनुबंध की विरासत) पर रचना का उपयोग करूं । क्योंकि, ऐसा करने से:
class Foo : IResetsPassword {
//...
}
आप तुरंत (संकलन समय पर) निर्दिष्ट कर रहे हैं कि आपकी कक्षा ' एक पासवर्ड रीसेट कर सकती है '। लेकिन, यदि आपके परिदृश्य में, क्षमता की उपस्थिति सशर्त है और अन्य चीजों पर निर्भर करती है, तो आप संकलन समय पर चीजों को निर्दिष्ट नहीं कर सकते। फिर, मैं यह करने का सुझाव देता हूं:
class Foo {
PasswordResetter passwordResetter;
}
अब, रनटाइम पर, आप myFoo.passwordResetter != null
यह ऑपरेशन करने से पहले देख सकते हैं । यदि आप सामान को और अधिक कम करना चाहते हैं (और आप कई और क्षमताओं को जोड़ने की योजना बना रहे हैं), तो आप कर सकते हैं:
class Foo {
//... foo stuff
}
class PasswordResetOperation {
bool Execute(Foo foo) { ... }
}
class SendMailOperation {
bool Execute(Foo foo) { ... }
}
//...and you follow this pattern for each new capability...
अद्यतन करें
जब मैंने ओपी से कुछ अन्य उत्तर और टिप्पणियां पढ़ीं, तो मुझे समझ में आया कि प्रश्न रचना समाधान के बारे में नहीं है। तो मुझे लगता है कि सवाल यह है कि सामान्य रूप से वस्तुओं की क्षमताओं की बेहतर पहचान कैसे की जाए, नीचे दिए गए परिदृश्य में:
class BaseAccount {
//...
}
class GuestAccount : BaseAccount {
//...
}
class UserAccount : BaseAccount, IMyPasswordReset, IEditPosts {
//...
}
class AdminAccount : BaseAccount, IPasswordReset, IEditPosts, ISendMail {
//...
}
//Capabilities
interface IMyPasswordReset {
bool ResetPassword();
}
interface IPasswordReset {
bool ResetPassword(UserAccount userAcc);
}
interface IEditPosts {
bool EditPost(long postId, ...);
}
interface ISendMail {
bool SendMail(string from, string to, ...);
}
अब, मैं उल्लिखित सभी विकल्पों का विश्लेषण करने की कोशिश करूँगा:
ओपी दूसरा उदाहरण:
if (account.CanResetPassword)
((IResetsPassword)account).ResetPassword();
else
Print("Not allowed to reset password with this account type!");
मान लीजिए कि यह कोड कुछ आधार खाता वर्ग प्राप्त कर रहा है (जैसे: BaseAccount
मेरे उदाहरण में); यह बुरा है क्योंकि यह बेस क्लास में बूलियन्स डाल रहा है, इसे कोड के साथ प्रदूषित कर रहा है जिससे कोई मतलब नहीं है।
ओपी पहला उदाहरण:
if (account is IResetsPassword)
((IResetsPassword)account).ResetPassword();
else
Print("Not allowed to reset password with this account type!");
प्रश्न का उत्तर देने के लिए, यह पिछले विकल्प की तुलना में अधिक उपयुक्त है, लेकिन कार्यान्वयन के आधार पर यह ठोस के एल सिद्धांत को तोड़ देगा, और शायद इस तरह की जाँच कोड के माध्यम से फैल जाएगी और आगे रखरखाव को और अधिक कठिन बना देगा।
CandiedOrange का ऐक्सरसाइज:
account.ResetPassword(authority);
यदि इस ResetPassword
विधि को BaseAccount
कक्षा में डाला जाता है , तो यह ओप के दूसरे उदाहरण की तरह, अनुचित कोड के साथ आधार वर्ग को भी प्रदूषित कर रहा है
स्नोमैन का जवाब:
AccountManager.resetPassword(otherAccount, adminAccount.getAccessToken());
यह एक अच्छा समाधान है, लेकिन यह मानता है कि क्षमताएं गतिशील हैं (और समय के साथ बदल सकती हैं)। हालाँकि, ओपी की कई टिप्पणियों को पढ़ने के बाद मुझे लगता है कि यहाँ बात बहुरूपता और सांख्यिकीय रूप से परिभाषित वर्गों के बारे में है (हालाँकि खातों का उदाहरण सहज परिदृश्य को इंगित करता है)। ईजी: इस AccountManager
उदाहरण में अनुमति के लिए चेक डीबी के लिए प्रश्न होंगे; ओपी प्रश्न में चेक ऑब्जेक्ट्स को कास्टिंग करने का प्रयास करते हैं।
मेरी ओर से एक और सुझाव:
उच्च स्तर की शाखाओं के लिए टेम्पलेट विधि पैटर्न का उपयोग करें। वर्ग पदानुक्रम का उल्लेख इस प्रकार रखा गया है; हम केवल वस्तुओं के लिए अधिक उपयुक्त हैंडलर बनाते हैं, ताकि आधार वर्ग को अनुचित बनाने वाले अनुचित गुणों / विधियों से बचा जा सके।
//Template method
class BaseAccountOperation {
BaseAccount account;
void Execute() {
//... some processing
TryResetPassword();
//... some processing
TrySendMail();
//... some processing
}
void TryResetPassword() {
Print("Not allowed to reset password with this account type!");
}
void TrySendMail() {
Print("Not allowed to reset password with this account type!");
}
}
class UserAccountOperation : BaseAccountOperation {
UserAccount userAccount;
void TryResetPassword() {
account.ResetPassword(...);
}
}
class AdminAccountOperation : BaseAccountOperation {
AdminAccount adminAccount;
override void TryResetPassword() {
account.ResetPassword(...);
}
void TrySendMail() {
account.SendMail(...);
}
}
आप डिक्शनरी / हैशटेबल का उपयोग करके ऑपरेशन को उपयुक्त खाता वर्ग में बाँध सकते हैं, या विस्तार विधियों का उपयोग करके रन-टाइम संचालन कर dynamic
सकते हैं, कीवर्ड का उपयोग कर सकते हैं, या अंतिम विकल्प के रूप में ऑपरेशन के लिए खाता ऑब्जेक्ट पास करने के लिए केवल एक कास्ट का उपयोग करें (में इस मामले में जातियों की संख्या केवल एक ही है, ऑपरेशन की शुरुआत में)।