পূর্ববর্তী অংশ:
একটি ক্লাস পরিবর্তন করার শুধুমাত্র একটি কারণ থাকা উচিত
// Bad class UserSettingsService { constructor(user: IUser) { this.user = user; } changeSettings(settings: IUserSettings): void { if (this.isUserValidated()) { // ... } } getUserInfo(): Promise<IUserSettings> { // ... } async isUserValidated(): Promise<boolean> { const userInfo = await this.getUserInfo(); // ... } }
এই উদাহরণে, আমাদের শ্রেণী বিভিন্ন দিকে ক্রিয়া সম্পাদন করে: এটি প্রসঙ্গ সেট আপ করে, এটি পরিবর্তন করে এবং এটি বৈধ করে।
// Better class UserAuth { constructor(user: IUser) { this.user = user; } getUserInfo(): Promise<IUserSettings> { // ... } async isUserValidated(): boolean { const userInfo = await this.getUserInfo(); // ... } } class UserSettings { constructor(user: IUser) { this.user = user; this.auth = new UserAuth(user); } changeSettings(settings: IUserSettings): void { if (this.auth.isUserValidated()) { // ... } } }
সফ্টওয়্যার সত্তা (ক্লাস, মডিউল, ফাংশন) এক্সটেনশনের জন্য খোলা থাকা উচিত কিন্তু পরিবর্তনের জন্য বন্ধ করা উচিত
// Bad class Product { id: number; name: string[]; price: number; protected constructor(id: number, name: string[], price: number) { this.id = id; this.name = name; this.price = price; } } class Ananas extends Product { constructor(id: number, name: string[], price: number) { super(id, name, price); } } class Banana extends Product { constructor(id: number, name: string[], price: string) { super(id, name, price); } } class HttpRequestCost { constructor(product: Product) { this.product = product; } getDeliveryCost(): number { if (product instanceOf Ananas) { return requestAnanas(url).then(...); } if (product instanceOf Banana) { return requestBanana(url).then(...); } } } function requestAnanas(url: string): Promise<ICost> { // logic for ananas } function requestBanana(url: string): Promise<ICost> { // logic for bananas }
এই উদাহরণে, সমস্যাটি হল HttpRequestCost
ক্লাসে, যেটি পদ্ধতিতে, getDeliveryCost
বিভিন্ন ধরনের পণ্যের গণনার শর্ত ধারণ করে এবং আমরা প্রতিটি ধরনের পণ্যের জন্য পৃথক পদ্ধতি ব্যবহার করি। সুতরাং, যদি আমাদের একটি নতুন ধরনের পণ্য যোগ করার প্রয়োজন হয়, তাহলে আমাদের HttpRequestCost
ক্লাসটি সংশোধন করা উচিত এবং এটি নিরাপদ নয়; আমরা অপ্রত্যাশিত ফলাফল পেতে পারি।
এটি এড়াতে, আমাদের উপলব্ধি ছাড়াই Product
শ্রেণিতে একটি বিমূর্ত পদ্ধতির request
তৈরি করা উচিত। বিশেষ উপলব্ধি ক্লাসগুলি উত্তরাধিকারসূত্রে প্রাপ্ত হবে: আনানস এবং কলা। তারা নিজেদের জন্য অনুরোধ বুঝতে হবে.
HttpRequestCost
Product
ক্লাস ইন্টারফেস অনুসরণ করে product
প্যারামিটার নেবে, এবং যখন আমরা HttpRequestCost
এ নির্দিষ্ট নির্ভরতা পাস করি, তখন এটি ইতিমধ্যে নিজের জন্য request
পদ্ধতি উপলব্ধি করবে।
// Better abstract class Product { id: number; name: string[]; price: string; constructor(id: number, name: string[], price: string) { this.id = id; this.name = name; this.price = price; } abstract request(url: string): void; } class Ananas extends Product { constructor(id: number, name: string[], price: string) { super(id, name, price); } request(url: string): void { // logic for ananas } } class Banana extends Product { constructor(id: number, name: string[], price: string) { super(id, name, price); } request(url: string): void { // logic for bananas } } class HttpRequestCost { constructor(product: Product) { this.product = product; } request(): Promise<void> { return this.product.request(url).then(...); } }
একটি সুপারক্লাসের অবজেক্টগুলিকে প্রয়োগ না করেই এর সাবক্লাসের বস্তুর সাথে প্রতিস্থাপনযোগ্য হওয়া উচিত।
// Bad class Worker { work(): void {/../} access(): void { console.log('Have an access to closed perimeter'); } } class Programmer extends Worker { createDatabase(): void {/../} } class Seller extends Worker { sale(): void {/../} } class Designer extends Worker { access(): void { throwError('No access'); } }
এই উদাহরণে, আমাদের Contractor
শ্রেণীর সাথে একটি সমস্যা আছে। Designer
, Programmer
এবং Seller
সবাই কর্মী, এবং তারা পিতামাতা শ্রেণির Worker
থেকে উত্তরাধিকার সূত্রে প্রাপ্ত। কিন্তু একই সময়ে, ডিজাইনারদের বদ্ধ পরিধিতে অ্যাক্সেস নেই কারণ তারা ঠিকাদার, কর্মচারী নয়। এবং আমরা access
মেথড ওভাররাইড করেছি এবং লিসকভ সাবস্টিটিউশন প্রিন্সিপল ভঙ্গ করেছি।
এই নীতিটি আমাদের বলে যে আমরা যদি সুপারক্লাস Worker
এর সাবক্লাস দিয়ে প্রতিস্থাপন করি, উদাহরণস্বরূপ Designer
ক্লাস, কার্যকারিতা ভাঙা উচিত নয়। কিন্তু যদি আমরা এটি করি, Programmer
ক্লাসের কার্যকারিতা ভেঙে যাবে - access
পদ্ধতিতে Designer
ক্লাস থেকে অপ্রত্যাশিত উপলব্ধি হবে।
// Better class Worker { work(): void {/../} } class Employee extends Worker { access(): void { console.log('Have an access to closed perimeter'); } } class Contractor extends Worker { addNewContract(): void {/../} } class Programmer extends Employee { createDatabase(): void {/../} } class Saler extends Employee { sale(): void {/../} } class Designer extends Contractor { makeDesign(): void {/../} }
আমরা Employee
এবং Contractor
বিমূর্তকরণের নতুন স্তর তৈরি করেছি এবং Employee
শ্রেণিতে access
পদ্ধতি স্থানান্তর করেছি এবং নির্দিষ্ট উপলব্ধি সংজ্ঞায়িত করেছি। আমরা যদি Worker
শ্রেণিকে সাবক্লাস Contractor
দিয়ে প্রতিস্থাপন করি, তাহলে Worker
কার্যকারিতা নষ্ট হবে না।