የሶፍትዌር አርክቴክቸር ምስጢሮችን በ Mastering Software Architecture ይክፈቱ፡ 11 ቁልፍ የንድፍ ንድፎች ተብራርተዋል ።
2. የንድፍ ንድፍ - አስማሚ
3. የንድፍ ንድፍ - ገንቢ
4. የኃላፊነት ሰንሰለትን እንዴት መጠቀም እንደሚቻል
5. የንድፍ ንድፍ - ጌጣጌጥ
6. የንድፍ ንድፍ - የፋብሪካ ዘዴ
7. የንድፍ ንድፍ - ኢተርተር
8. የንድፍ ንድፍ - አስታራቂ
9. የንድፍ ንድፍ - ተመልካች
10. የቅድሚያ ንብረት ንድፍ ሐ # 8.0
11. የንድፍ ንድፍ - ነጠላቶን
የጋንግ ፎር ፎር እንደሚለው፣ የአብስትራክት ፋብሪካ ንድፍ ፋብሪካዎችን ለመፍጠር እንደ ፋብሪካ ሊወሰድ ይችላል።
የአብስትራክት ፋብሪካ ንድፍ ብቻ የኤክስቴንሽን ፋብሪካ ዘዴ ነው; የአብስትራክት ፋብሪካን ንድፍ ከመረዳትዎ በፊት የፋብሪካውን ዘዴ ማለፍ ይመከራል.
እንደ ቁጠባ እና ወቅታዊ አካውንቶች ያሉ የመለያ ዓይነቶች ያለው የትኛውም ባንክ ተመሳሳይ ምሳሌን እንመልከት። አሁን፣ የአብስትራክት የፋብሪካ ንድፍ ንድፍን በመጠቀም ከላይ ያለውን ምሳሌ እንተገብረው።
በመጀመሪያ የISAvingAccount እና ICurrentAccount በይነገጾችን እንደሚከተለው ይተግብሩ።
public interface ISavingAccount{ } public interface ICurrentAccount{ }
ከዚህ በታች ባሉት ክፍሎች ውስጥ በይነገጹን ይውረሱ
public class CurrentAccount : ICurrentAccount { public CurrentAccount(string message) { Console.WriteLine(message); } } public class SavingsAccount : ISavingAccount { public SavingsAccount( string message) { Console.WriteLine(message); } }
ለእያንዳንዱ የመለያ አይነት የአብስትራክት ዘዴ ያለው አብስትራክት ክፍል እንፃፍ።
public abstract class AccountTypeFactory { public abstract ISavingAccount SavingAccountFactory(string message); public abstract ICurrentAccount CurrentAccountFactory(string message); }
አሁን፣ የአብስትራክት ዘዴዎችን ተግባራዊ የሚያደርግ “Bank1Factory” የሚባል የፋብሪካ ትግበራ እንፍጠር።
public class Bank1Factory : AccountTypeFactory { public override ICurrentAccount CurrentAccountFactory(string message) { return new CurrentAccount(message); } public override ISavingAccount SavingAccountFactory(string message) { return new SavingsAccount(message); } }
የአብስትራክት ፋብሪካ ዲዛይን ንድፍ የፋብሪካ አቅራቢን ለመተግበር ከሚያስፈልገው የፋብሪካ ዘዴ ይለያል, እንደ ፍቺው ፋብሪካዎችን ይመልሳል.
አሁን ሁሉም ረቂቅ እና ፋብሪካዎች ተፈጥረዋል. የፋብሪካ አቅራቢውን ዲዛይን እናድርግ። እባኮትን ለፋብሪካ አቅራቢው ኮድ ቅንጭብጭብ ከዚህ በታች ያግኙ፣ የማይለወጥ ዘዴ በመለያ ስሙ ላይ የተመሰረተ ፋብሪካ የሚፈጥር።
public class AccountFactoryProvider { public static AccountTypeFactory GetAccountTypeFactory(string accountName) { if (accountName.Contains("B1")) { return new Bank1Factory(); } else return null; } }
የሒሳብ ቁጥሮችን እንደ ምሳሌ እንውሰድ፣ የመለያ ስም በጥሬው “ B1 ”ን ካቀፈ፣ በፋብሪካ አቅራቢው በኩል የተመለሰውን የባንክ 1 ፋብሪካ ምሳሌ ይጠቀማል።
static void Main(string[] args) { List<string> accNames = new List<string> { "B1-456", "B1-987", "B2-222" }; for (int i = 0; i < accNames.Count; i++) { AccountTypeFactory anAbstractFactory = AccountFactoryProvider.GetAccountTypeFactory(accNames[i]); if (anAbstractFactory == null) { Console.WriteLine("Invalid " + (accNames[i])); } else { ISavingAccount savingAccount = anAbstractFactory.SavingAccountFactory("Hello saving"); ICurrentAccount currentAccount = anAbstractFactory.CurrentAccountFactory("Hello Current"); } } Console.ReadLine(); }
የመለያው ስም “B1” ቀጥተኛ ካልሆነ፣ ፕሮግራሙ ልክ ያልሆነ {{accountName}} ያወጣል።
እባኮትን ከላይ ካለው የኮድ ቅንጣቢ ውፅዓት በታች ያግኙ።
Hello saving B1-456 Hello Current B1-456 Hello saving B1-987 Hello Current B1-987
በጋንግ ኦፍ ፎር መሰረት፣ አስማሚው ስርዓተ ጥለት የአንድን ክፍል በይነገጾች ደንበኛው ወደ ሚፈልገው በይነ ይቀይራል።
በሌላ አነጋገር የአስማሚው ንድፍ ንድፍ ተኳኋኝ ያልሆኑ በይነገጾች በጋራ እንዲሰሩ ይረዳል።
ሁለት ድርጅቶች መቀላቀላቸውን እንደ ምሳሌ እንመልከት። X ድርጅት Yን እየወሰደ ነው፣ ነገር ግን ኮድን በማጣመር ላይ፣ በይነገጾቹ ተኳሃኝ አይደሉም። የድርጅቱ Y የግብይቶች ዝርዝር የሚያቀርበው በይነገጽ ከ X ጋር ተኳሃኝ እንዳልሆነ አስቡት።
ስለዚህ, የአስማሚው ንድፍ ንድፍ አተገባበሩ በጣም ቀላል የሆነውን ይህን ችግር ለመፍታት ይረዳል.
ከድርጅት Y የግብይቶች ዝርዝር እንፍጠር የድርጅቱ ደንበኛ አፕሊኬሽን X ወደ ሚፈልገው ቅጦች የተቀየሩ። ከላይ ያለው ክፍል “Adaptee” በመባል ይታወቃል።
public class OrgYTransactions { public List<string> GetTransactionsList() { List<string> transactions = new List<string>(); transactions.Add("Debit 1"); transactions.Add("Debit 2"); transactions.Add("Debit 3"); return transactions; } }
በሁለተኛ ደረጃ, የዒላማ በይነገጽ እንፍጠር.
public interface ITransactions{ List<string> GetTransactions(); }
አሁን በመጨረሻ፣ አስማሚውን ክፍል እንደሚከተለው እንተገብረው።
public class TransAdapter : OrgYTransactions, ITransactions { public List<string> GetTransactions() { return GetTransactionsList(); } }
ከላይ ያሉት ሁሉም አተገባበርዎች ከተከናወኑ በኋላ, በኮንሶል አፕሊኬሽን ውስጥ አስማሚውን ክፍል እንዴት እንደሚጠቀሙ እንረዳ.
class Program { static void Main(string[] args) { ITransactions adapter = new TransAdapter(); foreach (var item in adapter.GetTransactions()) { Console.WriteLine(item); } } }
ከዚህ በታች ያለውን አጠቃቀም በቅርበት ከተመለከቱ፣ የሶስተኛ ወገን ክፍል OrgYTransactions በይነገጾች እንዴት እንደሚመስሉ ሳናስብ የዒላማ በይነገጽ ITransactions እና አስማሚ ክፍል ትራንስአዳፕተር ተጠቅመናል። ያ ነው የአስማሚው የንድፍ ጥለት ሀይል የአንድን ክፍል በይነገጾች ደንበኛው ወደ ሚፈልገው በይነ ይቀይራል።
ጋንግ ኦፍ ፎር እንደሚለው፣ የፍጥረት ንድፍ “ገንቢ” አንድን ነገር ለመገንባት አንድን የተለየ ዘዴ ለመለየት እና እንደገና ለመጠቀም ያስችላል።
የመኪናውን ምሳሌ እንውሰድ, እና ተጠቃሚው ሁለት ሞዴሎችን ማለትም SUV እና Sedan መገንባት ፈልጎ ነበር.
የገንቢ ንድፍ ንድፍ ከላይ ባለው የአጠቃቀም ጉዳይ ላይ ጠቃሚ ነው, እና ደረጃ በደረጃ ማሳያን እንይ.
የመኪናው ክፍል የሚከተሉትን ባሕርያት አሉት.
public class Car{ public string Name { get; set; } public double TopSpeed { get; set; } public bool IsSUV { get; set; } }
በመጀመሪያ፣ እንደ አጠቃቀሙ ሁኔታ በተለያዩ የመኪና ሞዴሎች እንደ SUVs ወይም sedans የተራዘመ የአብስትራክት ክፍል ገንቢን እንተገበር።
public abstract class CarBuilder { protected readonly Car _car = new Car(); public abstract void SetName(); public abstract void SetSpeed(); public abstract void SetIsSUV(); public virtual Car GetCar() => _car; }
የአብስትራክት ክፍል የሚከተሉትን ዘዴዎች ያካትታል
አሁን፣ የተለያዩ የመኪና ሞዴሎችን ለመስራት የ CarBuilder ክፍልን የሚጠቀም እና የተሰራውን መኪና ምሳሌ የሚመልስ ፋብሪካ እንፍጠር።
public class CarFactory { public Car Build(CarBuilder builder) { builder.SetName(); builder.SetSpeed(); builder.SetIsSUV(); return builder.GetCar(); } }
በመጨረሻም የተለያዩ የመኪና ሞዴሎችን ይተግብሩ.
public class ModelSuv : CarBuilder { public override void SetIsSUV() { _car.IsSUV = true; } public override void SetName() { _car.Name = "Maruti SUV"; } public override void SetSpeed() { _car.TopSpeed = 1000; } }
public class ModelSedan : CarBuilder { public override void SetIsSUV() { _car.IsSUV = false; } public override void SetName() { _car.Name = "Maruti Sedan"; } public override void SetSpeed() { _car.TopSpeed = 2000; } }
በመጨረሻም በፋብሪካው እገዛ የተለያዩ የመኪና ሞዴሎችን ለመሥራት የንድፍ ንድፎችን እንጠቀም.ግንባታ (<ሞዴል>) ዘዴ.
static void Main(string[] args) { var sedan = new ModelSedan(); var suv = new ModelSuv(); var factory = new CarFactory(); var builders = new List<CarBuilder> { suv, sedan }; foreach (var b in builders) { var c = factory.Build(b); Console.WriteLine($"The Car details" + $"\n--------------------------------------" + $"\nName: {c.Name}" + $"\nIs SUV: {c.IsSUV}" + $"\nTop Speed: {c.TopSpeed} mph\n"); } }
ከላይ ያለው አጠቃቀም የአናጺውን ንድፍ በመጠቀም የተለያዩ የመኪና ሞዴሎችን እንዴት በጸጋ መገንባት እንደምንችል ያሳያል።
የኮዱ ንድፉ በጣም ሊጠበቅ የሚችል እና ሊሰፋ የሚችል ነው። ለወደፊቱ, አዲስ ሞዴል ማዘጋጀት ካስፈለገን, አዲሱ ሞዴል የ CarBuilder ክፍልን ማራዘም ብቻ ነው, እና ተከናውኗል.
የአራት ጋንግ እንደሚለው፣ ጥያቄን ለማስኬድ የኃላፊነት ሰንሰለት ይገልጻል። በሌላ አነጋገር አንድ ዕቃ ኃላፊነቱን እስኪቀበል ድረስ ጥያቄውን ከአንዱ ዕቃ ወደ ሌላው ያስተላልፉ።
በማንኛውም የድርጅት ኩባንያ ውስጥ የይገባኛል ጥያቄ ስርዓትን እንደ ምሳሌ እንመልከት። ሊፀድቅ የሚችል እና በማን የዋጋ ወሰን ዝርዝር ይኸውና.
100–1000 Rs => Junior/Senior Engineers => Approved by Manager 1001–10000 Rs => Managers => Approved by Senior Manager
ገንዘቡ ከ10000 ክልል ውጭ ከሆነ፣ ከዋናው አስተዳዳሪ ልዩ ፈቃድ ያስፈልጋል።
ከላይ ያለው የአጠቃቀም ጉዳይ የኃላፊነት ሰንሰለት ንድፍ ንድፍን በመጠቀም በቀላሉ ሊተገበር ይችላል. ስለዚህ, የይገባኛል ጥያቄው ክፍል የሚከተሉት ባህሪያት አሉት.
public class Claim{ public int Id{get;set;} public double amount{get;set;} }
በመጀመሪያ፣ የይገባኛል ጥያቄ አቅራቢው ምን አይነት ተግባራትን እንደሚፈጽም እንገልፅ እና በተለያዩ ደረጃዎች ላሉ ሰራተኞች ተዋረድን እናስቀምጥ። ከታች እንደሚታየው የአብስትራክት ክፍልን ተግባራዊ ያድርጉ
public abstract class ClaimApprover { protected ClaimApprover claimApprover; public void SetHierarchy(ClaimApprover claimApprover) { this.claimApprover = claimApprover; } public abstract void ApproveRequest(Claim claim); }
እንደ የአጠቃቀም ሁኔታ፣ የክፍል “ጁኒየር/አዛውንት” የይገባኛል ጥያቄ አቅራቢን እንነዳው። ይህ ክፍል/የሰራተኞች ምደባ ማንኛውንም የይገባኛል ጥያቄ ማጽደቅ እንደማይችል አስተውል።
public class Junior : ClaimApprover { public override void ApproveRequest(Claim claim) { System.Console.WriteLine("Cannot approve"); } }
በተመሳሳይ፣ ለአስተዳዳሪ እና ለከፍተኛ አስተዳዳሪ ሚናዎች አተገባበርን እንግለጽ።
public class Manager : ClaimApprover { public override void ApproveRequest(Claim claim) { if (claim.amount >= 100 && claim.amount <= 1000) { System.Console.WriteLine($"Claim reference {claim.Id} with amount {claim.amount} is approved by Manager"); } else if (claimApprover != null) { claimApprover.ApproveRequest(claim); } } }
በመጠን ክልል ላይ በመመስረት በአስተዳዳሪው ክልል ውስጥ ከሆነ የይገባኛል ጥያቄው በአስተዳዳሪው ሊፀድቅ እንደሚችል ልብ ይበሉ; አለበለዚያ ጥያቄው ወደ ከፍተኛ ሥራ አስኪያጅ ይተላለፋል.
public class SeniorManager : ClaimApprover { public override void ApproveRequest(Claim claim) { if (claim.amount > 1000 && claim.amount <= 10000) { System.Console.WriteLine($"Claim reference {claim.Id} with amount {claim.amount} is approved by Senior Manager"); } else { System.Console.WriteLine($"Exceptional approval for Claim reference {claim.Id} with amount {claim.amount} is approved by Senior Manager"); } } }
በተመሳሳይም መጠኑ በሲኒየር ሥራ አስኪያጅ ክልል ውስጥ ከሆነ የይገባኛል ጥያቄው በአስተዳዳሪው ሊፀድቅ ይችላል; ያለበለዚያ፣ በተዋረድ ውስጥ የመጨረሻው በመሆኑ፣ ከክልሉ ውጭ ላለ መጠን ልዩ ማፅደቅ ይደረጋል።
ClaimApprover junior = new Manager(); ClaimApprover sukhpinder = new Manager(); ClaimApprover singh = new SeniorManager(); junior.SetHierarchy(sukhpinder); sukhpinder.SetHierarchy(singh); Claim c1 = new Claim() { amount = 999, Id = 1001 }; Claim c2 = new Claim() { amount = 10001, Id = 1002 }; junior.ApproveRequest(c1); sukhpinder.ApproveRequest(c2);
Claim reference 1001 with amount 999 is approved by Manager Exceptional approval for Claim reference 1002 with amount 10001 is approved by Senior Manager
ለመስመር 1 ውፅዓት፣ መጠኑ በክልል ውስጥ ነበር፣ ስለዚህ ስራ አስኪያጁ አጽድቆታል።
ለመስመር 2 ውፅዓት፣ ምንም እንኳን ከፍተኛ ስራ አስኪያጁ ቢፈቅድም፣ መጠኑ ከክልሉ ውጭ ነበር።
በጋንግ ኦፍ ፎር መሰረት፣ ንድፉ ለተለዋዋጭ ክፍል ተጨማሪ ሀላፊነቶችን ይጨምራል።
አሥር ሺሕ ብር ዋጋ ያለው መኪና የመግዛትን ምሳሌ እንመልከት። ኩባንያው የሚከተሉትን ተጨማሪ ባህሪያት ያቀርባል.
በአንዳንድ ተጨማሪ ባህሪያት, የመኪናው አጠቃላይ ዋጋ ይጨምራል. የማስጌጫ ንድፍን በመጠቀም ከላይ ያለውን የአጠቃቀም መያዣ እንተገብረው።
ከላይ የተገለጸውን የአጠቃቀም ሁኔታ እንተገብረው። በመጀመሪያ፣ የአብስትራክት ክፍል መኪናን እና መሰረታዊ ስልቶቹን ይግለጹ።
public abstract class Car{ public abstract int CarPrice(); public abstract string GetName(); }
ከአብስትራክት ክፍል መኪና በላይ የምትዘረጋ አንዲት ትንሽ መኪና አስብ።
public class SmallCar : Car{ public override int CarPrice() => 10000; public override string GetName() => "Alto Lxi"; }
አሁን, የመኪናውን አካል በመጠቀም የ CarDecorator ክፍልን ይተግብሩ.
public class CarDecorator : Car { protected Car _car; public CarDecorator(Car car) { _car = car; } public override int CarPrice() => _car.CarPrice(); public override string GetName() =>_car.GetName(); }
አሁን፣ ለ CarDecorator ክፍል ለሚወርሰው ለእያንዳንዱ ተጨማሪ ባህሪ የተለየ ክፍል እንፍጠር።
እንደ አጠቃቀሙ ሁኔታ, ተጨማሪ ባህሪያት የፀሐይ ጣራ እና የላቀ የሙዚቃ ስርዓት ናቸው.
እንደ ዘዴዎቹ ይሽሩ
በጠቅላላ የመኪና ዋጋ ላይ የ"ከፍተኛ የሙዚቃ ስርዓት" ተጨማሪ ወጪን ይጨምሩ።
የመኪና ስም ከተጨማሪ ባህሪ ስም ጋር ያዘምኑ።
public class AdvanceMusic : CarDecorator { public AdvanceMusic(Car car) : base(car) { } public override int CarPrice() => _car.CarPrice() + 3000; public override string GetName()=> "Alto Lxi with advance music system"; }
እንደ ዘዴዎቹ ይሽሩ
public class Sunroof : CarDecorator { public Sunroof(Car car) : base(car) { } public override int CarPrice() => _car.CarPrice() + 2000; public override string GetName() => "Alto Lxi with Sunroof"; }
የ SmallCar ምሳሌ ፍጠር እና የመኪናውን ስም እና ዋጋ አውጣ።
Car car = new SmallCar(); Console.WriteLine($"Price of car {car.GetName()} : " + car.CarPrice());
አሁን፣ ከታች እንደሚታየው ተጨማሪ ባህሪያትን እንጨምር
var car1 = new Sunroof(car); var car2 = new AdvanceMusic(car);
static void Main(string[] args) { Car car = new SmallCar(); Console.WriteLine($"Price of car {car.GetName()} : " + car.CarPrice()); var car1 = new Sunroof(car); Console.WriteLine($"Price of car {car1.GetName()} : " + car1.CarPrice()); var car2 = new AdvanceMusic(car); Console.WriteLine($"Price of car {car2.GetName()} : " + car2.CarPrice()); }
እንኳን ደስ አለን..!! የማስዋቢያውን ንድፍ በመጠቀም የአጠቃቀም መያዣውን በተሳካ ሁኔታ ተግባራዊ አድርገዋል።
በጋንግ ኦፍ ፎር መሠረት የፋብሪካው ዘዴ የትኛው ክፍል መፈጠር እንዳለበት ለመወሰን ንዑስ ክፍል ይፈቅዳል.
እንደ ቁጠባ እና ወቅታዊ አካውንት ያለው የትኛውንም ባንክ እንደ ምሳሌ እንውሰድ። አሁን, የፋብሪካውን ንድፍ ንድፍ በመጠቀም ከላይ ያለውን ምሳሌ እንተገብረው
በመጀመሪያ፣ የመለያ አይነት አብስትራክት ክፍል ይፍጠሩ።
public abstract class AccoutType { public string Balance { get; set; } }
ከዚህ በታች እንደሚታየው የአካውንት ዓይነት አብስትራክት ክፍልን በመውረስ የአሁን እና ቁጠባ ክፍሎችን ይተግብሩ።
public class SavingsAccount : AccoutType { public SavingsAccount() { Balance = "10000 Rs"; } } public class CurrentAccount : AccoutType { public CurrentAccount() { Balance = "20000 Rs"; } }
በመጨረሻም, የክፍል ነገር ለመፍጠር የሚያግዝ ውል የሚያቀርበውን የፋብሪካ በይነገጽ እንተገብረው. ይህ በይነገጽ ፈጣሪ በመባልም ይታወቃል።
public interface IAccountFactory { AccoutType GetAccoutType(string accountName); }
በመጨረሻ ፣ ከዚህ በታች እንደሚታየው የፈጣሪ በይነገጽ ዘዴን ትግበራ ይፃፉ። ፈጣሪን ተግባራዊ የሚያደርግ ክፍል ኮንክሪት ፈጣሪ በመባል ይታወቃል።
public class AccountFactory : IAccountFactory { public AccoutType GetAccoutType(string accountName) { if (accountName.Equals("SAVINGS", StringComparison.OrdinalIgnoreCase)) { return new SavingsAccount(); } else if (accountName.Equals("CURRENT", StringComparison.OrdinalIgnoreCase)) { return new CurrentAccount(); } else { throw new ArgumentException("Invalid account name"); } } }
ያ ነው. የባንኩን ምሳሌ በመጠቀም የፋብሪካውን ዘዴ በተሳካ ሁኔታ ተግባራዊ አድርገዋል.
አንድ ንዑስ ክፍል በመለያው ስም ላይ በመመስረት የትኛው "የመለያ አይነት" ክፍል ነገር እንደሚፈጠር ይወስናል.
class Program { static void Main(string[] args) { IAccountFactory accountFactory = new AccountFactory(); var savingAccount = accountFactory.GetAccoutType("SAVINGS"); Console.WriteLine("Saving account balance: " + savingAccount.Balance); var currentAccount = accountFactory.GetAccoutType("CURRENT"); Console.WriteLine("Current account balance: " + currentAccount.Balance); } }
ለምሳሌ የመለያው ስም “SAVINGS” ከሆነ “SavingAccount” ክፍል ነገር ተፈጠረ እና ይመለሳል።
በተመሳሳይ፣ የመለያው ስም “CURRENT” ከሆነ፣ “CurrentAccount” ክፍል ነገር በቅጽበት ይወሰድና ይመለሳል።
Saving account balance: 10000 Rs Current account balance: 20000 Rs
ጋንግ ኦፍ ፎር እንዳለው፣ የድጋሚው ንድፍ አተገባበሩን ሳያውቅ ሰብሳቢውን ነገር ለማግኘት ሂደትን ይሰጣል።
የመኪኖች እና ሕብረቁምፊዎች ስብስብ ምሳሌ እንደ ምሳሌ እንውሰድ፣ የተደራጁ የሞተር ሳይክሎች፣ አንድ ሰው ዝርዝር ወይም ድርድር መሆኑን ሳያውቅ ክምችቱን ለመድገም እንዲችል ሰብሳቢ ነገር መንደፍ አለብን።
የእንደገና ንድፍ ንድፍ ይህንን ችግር ለመፍታት ይረዳል, ይህም መደበኛ ተደጋጋሚ የተለያዩ የመሰብሰቢያ ዓይነቶችን ይሻገራል.
ከላይ ያለውን የአጠቃቀም ሁኔታ ከግምት ውስጥ በማስገባት በዝርዝሩ ላይ እንደ ረቂቅ ንብርብር የሚያገለግል ብጁ የድግግሞሽ በይነገጽ እንገልፃለን።
public interface IVehicleIterator{ void First(); bool IsDone(); string Next(); string Current(); }
አሁን በአጠቃቀም ሁኔታው መሰረት ከላይ ያለውን በይነገጽ የሚተገብሩ የመኪና እና የሞተር ሳይክል ድግግሞሾችን ይፃፉ።
public class CarIterator : IVehicleIterator { private List<string> _cars; private int _current; public CarIterator(List<string> cars) { _cars = cars; _current = 0; } public string Current() { return _cars.ElementAt(_current); } public void First() { _current = 0; } public bool IsDone() { return _current >= _cars.Count; } public string Next() { return _cars.ElementAt(_current++); } }
የመኪና ተደጋጋሚው በዝርዝር<string> ክምችት ላይ ተተግብሯል እና የበይነገጽ ዘዴዎችን ተግባራዊ ያደርጋል።
የሞተርሳይክል ድግግሞሹ በገመድ ክምችት ላይ የተተገበረ ሲሆን የበይነገጽ ዘዴዎችን ተግባራዊ ያደርጋል።
public class MotercycleIterator : IVehicleIterator { private string[] _motercylces; private int _current; public MotercycleIterator(string[] motercylces) { _motercylces = motercylces; _current = 0; } public string Current() { return _motercylces[_current]; } public void First() { _current = 0; } public bool IsDone() { return _current >= _motercylces.Length; } public string Next() { return _motercylces[_current++]; } }
ከላይ ያሉት ሁሉም ድግግሞሾች ከተገለጹ በኋላ፣ ተደጋጋሚዎችን የሚፈጥር መደበኛ ሰብሳቢ ነገር በይነገጽ ይግለጹ።
public interface IVehicleAggregate{ IVehicleIterator CreateIterator(); }
በመጨረሻም, ከላይ ያለውን የአሰባሳቢ በይነገጽ የሚተገበሩትን ክፍሎች ይፃፉ. በአጠቃቀም ሁኔታው መሰረት ሁለቱም የመኪና እና የሞተር ሳይክል ክፍሎች የአሰባሳቢውን በይነገጽ ተግባራዊ ያደርጋሉ።
የአጎራባች በይነገጽ ዘዴ ከዚህ በታች እንደሚታየው ተገቢውን ተደጋጋሚነት ይመልሳል።
public class Car : IVehicleAggregate { private List<string> _cars; public Car() { _cars = new List<string> { "Car 1", "Car 2", "Car 3" }; } public IVehicleIterator CreateIterator() { return new CarIterator(_cars); } }
የአጎራባች በይነገጽ ዘዴ ከዚህ በታች እንደሚታየው ተገቢውን ተደጋጋሚነት ይመልሳል።
public class Motercycle : IVehicleAggregate { private string[] _motercycles; public Motercycle() { _motercycles = new[] { "Bike 1", "Bike 2", "Bike 3" }; } public IVehicleIterator CreateIterator() { return new MotercycleIterator(_motercycles); } }
የPrintVehicles ዘዴዎች !iterator.isDone ከሆነ የስብስብ ኤለመንቱን ካወጡት ያረጋግጡ። ከየትኛውም ስብስብ ጋር እየተገናኘን ብንሆን እንደ ፈርስት፣ አይኤስዶን እና ቀጣይ ያሉ ዘዴዎችን ይተግብሩ።
static void Main(string[] args) { IVehicleAggregate car = new Vehicles.Car(); IVehicleAggregate motercycle = new Vehicles.Motercycle(); IVehicleIterator carIterator = car.CreateIterator(); IVehicleIterator motercycleIterator = motercycle.CreateIterator(); PrintVehicles(carIterator); PrintVehicles(motercycleIterator); } static void PrintVehicles(IVehicleIterator iterator) { iterator.First(); while (!iterator.IsDone()) { Console.WriteLine(iterator.Next()); } }
ከስር ያለውን የስብስብ አይነት አናውቅም፣ ነገር ግን አሁንም በ Iterator Design Pattern በኩል ተደግሟል። ወደፊት ከሄዱ እና ከሮጡ የሚከተለውን ውፅዓት ያሳያል።
ጋንግ ኦፍ ፎር እንደሚለው፣ የሽምግልና ንድፍ እርስ በርስ የነገሮችን መስተጋብር ያጠቃልላል።
የሽምግልና ንድፍ ንድፍ የነገር መስተጋብርን በማካተት በቀላሉ የተጣመሩ መተግበሪያዎችን ለመንደፍ ይረዳናል።
ተሳታፊዎች የሚመዘገቡበት የቻት ሩም ምሳሌ እና እንዴት በብቃት እንደሚግባቡ እንይ።
የሽምግልና ዲዛይን ንድፍን በመጠቀም የሚከተለውን የቻት ሩም ውይይት መተግበር ያስፈልጋል።
David to Scott: 'Hey' Scott to David: 'I am good how about you.' Jennifer to Ashley: 'Hey ashley... david is back in the group' Jennifer to David: 'Where have you been?' Ashley to David: 'How come you aren't active here anymore?'
ዋናው እርምጃ በቻት ሩም ውስጥ ጥቅም ላይ የሚውሉ የተጠቃሚ ስሞችን ዝርዝር መፍጠር ነው። ለዚያ ይፋዊ ዝርዝር ከዚህ በታች ይታያል።
public enum Username{ Ashley, David, Jennifer, Scott }
አሁን፣ በመጀመሪያ፣ የቻት ሩም ረቂቅ ንብርብርን ይተግብሩ።
public abstract class AChatroom { public abstract void Register(User user); public abstract void Post(string fromUser, string toUser, string msg); }
እና ረቂቅ ዘዴዎችን የሚገልጽ ክፍል። ዘዴዎቹ ተጠቃሚው በመዝገበ-ቃላቱ ውስጥ ካለ ያረጋግጣሉ። ለምሳሌ፣ የመመዝገቢያ ዘዴው ተጠቃሚው ካለ ወይም ከሌለ ያረጋግጣል። ከሌለ ተጠቃሚውን በቻት ሩም ውስጥ ብቻ ይመዝገቡ።
public class Chatroom : AChatroom { private Dictionary<string, User> _users = new Dictionary<string, User>(); public override void Post(string fromUser, string toUser, string msg) { User participant = _users[toUser]; if (participant != null) { participant.DM(fromUser, msg); } } public override void Register(User user) { if (!_users.ContainsValue(user)) { _users[user.Name] = user; } user.Chatroom = this; } }
በመጨረሻም፣ ተጠቃሚው የሚያደርጋቸውን ተግባራት፣ ለምሳሌ በቻት ሩም ውስጥ ለተጠቃሚ መልእክት መለጠፍ ወይም DM ከሌላ ተጠቃሚ መቀበልን የመሳሰሉ ተግባራትን እናድርገው።
public class User { private Chatroom _chatroom; private string _name; public User(string name) => this._name = name; public string Name => _name; public Chatroom Chatroom { set { _chatroom = value; } get => _chatroom; } public void Post(string to, string message) => _chatroom.Post(_name, to, message); public virtual void DM(string from, string message) => Console.WriteLine("{0} to {1}: '{2}'", from, Name, message); }
static void Main(string[] args) { Chatroom chatroom = new Chatroom(); User Jennifer = new UserPersona(Username.Jennifer.ToString()); User Ashley = new UserPersona(Username.Ashley.ToString()); User David = new UserPersona(Username.David.ToString()); User Scott = new UserPersona(Username.Scott.ToString()); chatroom.Register(Jennifer); chatroom.Register(Ashley); chatroom.Register(David); chatroom.Register(Scott); David.Post(Username.Scott.ToString(), "Hey"); Scott.Post(Username.David.ToString(), "I am good how about you."); Jennifer.Post(Username.Ashley.ToString(), "Hey ashley... david is back in the group"); Jennifer.Post(Username.David.ToString(), "Where have you been?"); Ashley.Post(Username.David.ToString(), "How come you aren't active here anymore?"); Console.ReadKey(); }
የፕሮግራሙ አፈፃፀም የተጠቃሚውን ክፍል የፖስታ ዘዴን ብቻ ይገልጻል።
ውጤት ፡ ከላይ ያለው የፕሮግራም አፈፃፀም የቻት ሩም ታሪክ
David to Scott: 'Hey' Scott to David: 'I am good how about you.' Jennifer to Ashley: 'Hey ashley... david is back in the group' Jennifer to David: 'Where have you been?' Ashley to David: 'How come you aren't active here anymore?'
በጋንግ ኦፍ ፎር መሰረት፣ የተመልካቹ ንድፍ ጥገኝነትን b/w ሁለት ወይም ከዚያ በላይ ነገሮችን ይገልፃል። ስለዚህ፣ አንድ ነገር ሁኔታ ሲቀየር፣ ሁሉም ጥገኞቹ እንዲያውቁት ይደረጋል።
በሌላ አነጋገር የአንድ ነገር ለውጥ በሌላ ነገር ውስጥ ማሳወቂያውን ይጀምራል.
የ “ x ” ተከታዮች ብዛት ያለው የኢንስታግራም ዝነኛ ተፅእኖ ፈጣሪን እንደ ምሳሌ እንውሰድ። ስለዚህ፣ ታዋቂው ሰው ልጥፍ ባከለበት ቅጽበት፣ ሁሉም ተከታዮች እንዲያውቁት ይደረጋል።
ከላይ የተጠቀሰውን የአጠቃቀም ጉዳይ የ Observer Design Pattern በመጠቀም እንተገብረው።
በአጠቃቀም ሁኔታው መሠረት, የመጀመሪያው አንድ ታዋቂ ሰው ሊፈጽማቸው የሚችሉትን ድርጊቶች የያዘውን በይነገጽ ተግባራዊ ያደርጋል. እሱም " ርዕሰ ጉዳይ " በመባል ይታወቃል.
public interface ICelebrityInstagram{ string FullName { get; } string Post { get; set; } void Notify(string post); void AddFollower(IFollower fan); void RemoveFollower(IFollower fan); }
አሳውቅ ፡ ለሁሉም ተከታዮች ለማሳወቅ።
AddFollower ፡ አዲስ ተከታይ ወደ የታዋቂ ሰዎች ዝርዝር ያክሉ።
አስወግድ ተከታይ ፡ ተከታይን ከታዋቂ ሰዎች ዝርዝር ውስጥ አስወግድ።
አሁን፣ ለማሳወቂያ የ«አዘምን» አባል ተግባርን የያዘውን የተመልካች «IFollower» በይነገጽን ተግብር።
public interface IFollower{ void Update(ICelebrityInstagram celebrityInstagram); }
በመጨረሻም፣ ለሁለቱም “ ርዕሰ ጉዳይ ” እና “ ተመልካች ” “የኮንክሪት ትግበራ”ን ተግባራዊ ለማድረግ ጊዜው አሁን ነው።
የታዋቂውን ስም እና ወደ ኮንሶሉ የሚለጥፈውን የዝማኔ አባል ተግባር ትግበራ ያቀርባል።
public class Follower : IFollower { public void Update(ICelebrityInstagram celebrityInstagram) { Console.WriteLine($"Follower notified. Post of {celebrityInstagram.FullName}: " + $"{celebrityInstagram.Post}"); } }
public class Sukhpinder : ICelebrityInstagram { private readonly List<IFollower> _posts = new List<IFollower>(); private string _post; public string FullName => "Sukhpinder Singh"; public string Post { get { return _post; } set { Notify(value); } } public void AddFollower(IFollower follower) { _posts.Add(follower); } public void Notify(string post) { _post = post; foreach (var item in _posts) { item.Update(this); } } public void RemoveFollower(IFollower follower) { _posts.Remove(follower); } }
የሚከተለው የአጠቃቀም ሁኔታ የሚያሳየው ከዚህ በታች ያለው መግለጫ ሲተገበር ነው። የማሻሻያ ዘዴው ለእያንዳንዱ ተከታይ ተቀስቅሷል፣ ማለትም፣ እያንዳንዱ ተከታይ ነገር ከ"ሱክፒንደር" አዲስ ልጥፍ እንዲያውቀው ይደረጋል።
static void Main(string[] args) { var sukhpinder = new Sukhpinder(); var firstFan = new Follower(); var secondFan = new Follower(); sukhpinder.AddFollower(firstFan); sukhpinder.AddFollower(secondFan); sukhpinder.Post = "I love design patterns."; Console.Read(); }
ጽሑፉ የስርዓተ-ጥለት ማዛመድ እንዴት ውሂቡን ለመጠቀም እና ለማስኬድ የዋናው ስርዓት አካል ባልሆኑ ቅጾች እንዴት ውጤታማ መንገድ እንደሚያቀርብ ይገልጻል።
የቶል ካልኩሌተርን ምሳሌ እንውሰድ እና ስርዓተ ጥለት ማዛመድ ለዛ አልጎሪዝም ለመጻፍ እንዴት እንደሚያግዝ እንይ።
public class Car { public int PassengerCount { get; set; } } public class DeliveryTruck { public int Weight { get; set; } } public class Taxi { public int Fare { get; set; } } public class Bus { public int Capacity { get; set; } public int RidersCount { get; set; } }
ምሳሌ 1፡ የክፍያ ታሪፍ በሚከተሉት ሁኔታዎች አስላ፡
- ተሽከርካሪው መኪና ከሆነ => 100 ብር
- ተሽከርካሪው DeliveryTruck => 200 Rs ከሆነ
- ተሽከርካሪው አውቶቡስ ከሆነ => 150 ብር
- ተሽከርካሪው ታክሲ ከሆነ => 120 ብር
የተሽከርካሪው አይነት ከመኪና 100 ጋር የሚመሳሰል ከሆነ ተመልሷል ወዘተ. ባዶ እና {} ለነገሩ አይነት ነባሪ ጉዳዮች መሆናቸውን ልብ ይበሉ።
እንዲሁም፣ “_” ነባሪውን ሁኔታ ፕሮግራም ለማድረግ ጥቅም ላይ ሊውል ይችላል። አዲስ የመቀየሪያ አገባብ ይመልከቱ።
ይበልጥ ንፁህ እና ቀልጣፋ የመቀየሪያ መንገድ ነው እና እንዲሁም በነጠላ ፊደላት ተለዋዋጭ ስሞችን በመቀየሪያ አገባብ ውስጥ እንዲጠቀሙ ይመከራል።
public static int TollFare(Object vehicleType) => vehicleType switch { Car c => 100, DeliveryTruck d => 200, Bus b => 150, Taxi t => 120, null => 0, { } => 0 };
ከኮንሶል መተግበሪያ እይታ ምሳሌዎችን ይሞክሩ። ከዚህ በታች ያለው ኮድ ከላይ ያለውን ስርዓተ-ጥለት-ማዛመጃ ተግባርን ከዋናው ዘዴ እንዴት መጥራት እንደሚቻል ያሳያል።
var car = new Car(); var taxi = new Taxi(); var bus = new Bus(); var truck = new DeliveryTruck(); Console.WriteLine($"The toll for a car is {TollFare(car)}"); Console.WriteLine($"The toll for a taxi is {TollFare(taxi)}"); Console.WriteLine($"The toll for a bus is {TollFare(bus)}"); Console.WriteLine($"The toll for a truck is {TollFare(truck)}");
The toll for a car is 100 The toll for a taxi is 120 The toll for a bus is 150 The toll for a truck is 200
ምሳሌ 2፡ በተሽከርካሪ ዓይነት ላይ በመመስረት የመኖሪያ ዋጋን ይጨምሩ
- መኪናዎች እና ታክሲዎች "አይ" ተሳፋሪዎች ተጨማሪ 10 Rs ይከፍላሉ።
- ሁለት ተሳፋሪዎች ያሏቸው መኪኖች እና ታክሲዎች የ10 Rs ቅናሽ ያገኛሉ።
- ሶስት ወይም ከዚያ በላይ ተሳፋሪዎች ያሏቸው መኪኖች እና ታክሲዎች የ20 Rs ቅናሽ ያገኛሉ።
- ከ50% በታች የሆኑ አውቶቡሶች ተጨማሪ 30 Rs ይከፍላሉ።
- ከ90% በላይ መንገደኞች ያሏቸው አውቶቡሶች የ40 Rs ቅናሽ ያገኛሉ።
- ከ 5000 ፓውንድ በላይ የሆኑ የጭነት መኪናዎች ተጨማሪ 100 Rs ይከፍላሉ.
- ቀላል መኪናዎች ከ3000 ፓውንድ በታች፣ የ20 Rs ቅናሽ ተሰጥቷቸዋል።
ከነጠላ እና ከበርካታ የንብረት ክፍሎች ጋር ከስርዓተ-ጥለት ጋር የሚዛመድ አገባብ ይመልከቱ። አገናኝ
Car { PassengerCount: 0 } => 100 + 10, Car { PassengerCount: 1 } => 100, Car { PassengerCount: 2 } => 100 - 10, Car c => 100 - 20,
Taxi {Fare:0 }=>100+10, Taxi { Fare: 1 } => 100, Taxi { Fare: 2 } => 100 - 10, Taxi t => 100 - 20,
Bus b when ((double)b.RidersCount / (double)b.Capacity) < 0.50 => 150 + 30, Bus b when ((double)b.RidersCount / (double)b.Capacity) > 0.90 => 150 - 40, Bus b => 150,
DeliveryTruck t when (t.Weight > 5000) => 200 + 100, DeliveryTruck t when (t.Weight < 3000) => 200 - 20, DeliveryTruck t => 200,
ከታች ያለው ምሳሌ የስርዓተ-ጥለት ማዛመድን ጥቅሞች ጎላ አድርጎ ያሳያል-የስርዓተ-ጥለት ቅርንጫፎች በቅደም ተከተል ይሰበሰባሉ. አቀናባሪው ስለማይደረስበት ኮድም ያስጠነቅቃል።
public static int OccupancyTypeTollFare(Object vehicleType) => vehicleType switch { Car { PassengerCount: 0 } => 100 + 10, Car { PassengerCount: 1 } => 100, Car { PassengerCount: 2 } => 100 - 10, Car c => 100 - 20, Taxi { Fare: 0 } => 100 + 10, Taxi { Fare: 1 } => 100, Taxi { Fare: 2 } => 100 - 10, Taxi t => 100 - 20, Bus b when ((double)b.RidersCount / (double)b.Capacity) < 0.50 => 150 + 30, Bus b when ((double)b.RidersCount / (double)b.Capacity) > 0.90 => 150 - 40, Bus b => 150, DeliveryTruck t when (t.Weight > 5000) => 200 + 100, DeliveryTruck t when (t.Weight < 3000) => 200 - 20, DeliveryTruck t => 200, null => 0, { } => 0, };
ከኮንሶል መተግበሪያ እይታ ምሳሌዎችን ይሞክሩ። ከዚህ በታች ያለው ኮድ ከላይ ያለውን ስርዓተ-ጥለት-ማዛመጃ ተግባርን ከዋናው ዘዴ እንዴት መጥራት እንደሚቻል ያሳያል።
var car1 = new Car{ PassengerCount=2}; var taxi1 = new Taxi { Fare = 0 }; var bus1 = new Bus { Capacity = 100, RidersCount = 30 }; var truck1 = new DeliveryTruck { Weight = 30000 }; Console.WriteLine($"The toll for a car is {OccupancyTypeTollFare(car1)}"); Console.WriteLine($"The toll for a taxi is {OccupancyTypeTollFare(taxi1)}"); Console.WriteLine($"The toll for a bus is {OccupancyTypeTollFare(bus1)}"); Console.WriteLine($"The toll for a truck is {OccupancyTypeTollFare(truck1)}");
The toll for a car is 90 The toll for a taxi is 110 The toll for a bus is 180 The toll for a truck is 300
"ስርዓተ-ጥለት ማዛመድ ኮድን የበለጠ ተነባቢ ያደርገዋል እና ወደ ክፍሎችዎ ኮድ ማከል በማይችሉበት ጊዜ ከቁስ-ተኮር ቴክኒኮች ሌላ አማራጭ ይሰጣል።"
የአራት ቡድን - የነጠላቶን ንድፍ ንድፍ አንድ የተወሰነ ክፍል አንድ ምሳሌ/ነገር ብቻ እና አለምአቀፍ የመዳረሻ ነጥብ እንዳለው ያረጋግጣል።
የነጠላቶን ክፍሎች የአንድ የተወሰነ ክፍል ከአንድ በላይ ነገሮችን ፈጣን ለማስወገድ ያገለግላሉ።
public class SingletonExample { private string Name { get; set; } = "Hello from singleton"; private static SingletonExample _instance; public static SingletonExample Instance { get { if (_instance == null) { _instance = new SingletonExample(); } return _instance; } } public SingletonExample() { } public string GetName() => Name; }
ነጠላውን ክፍል ሁለት ጊዜ እንጥራውና የተመለሰውን ምሳሌ ለሁለት የተለያዩ ተለዋዋጮች እንመድበው። በመጨረሻም የObject.Equals ተግባርን በመጠቀም ሁለቱም ነገሮች እኩል መሆናቸውን ያረጋግጡ።
static void Main(string[] args) { var response = SingletonExample.Instance; Console.WriteLine(response); var response1 = SingletonExample.Instance; Console.WriteLine(response1); Console.WriteLine(Object.Equals(response1, response)); }
የኮንሶል ውፅዓት ወደ እውነት ይመለሳል; እንኳን ደስ አላችሁ። የነጠላቶን ንድፍን በተሳካ ሁኔታ ተግባራዊ አድርገዋል።
ከላይ ያለው ክፍል የነጠላቶን ክፍል በመባል ይታወቃል፣ አሁን ግን በክር-አስተማማኝ አይደለም። ባለብዙ-ክር አካባቢ፣ በአንድ ጊዜ (_ለምሳሌ == ባዶ) መግለጫ ከሆነ ሁለት ክሮች ሊመታ ይችላል፣ እና መጨረሻ ላይ የአንድ ነጠላ ቶን ክፍል በርካታ አጋጣሚዎች ይኖሩናል።
ለአስተማማኝ ክር አንዱ መንገድ የመቆለፊያ ዘዴን መጠቀም ሲሆን ሌላኛው መንገድ ለንጹህ እና የበለጠ ቀልጣፋ አቀራረብ ለንባብ ብቻ ምሳሌ ማድረግ ነው።
public class ThreadSafeSingleton { private static readonly ThreadSafeSingleton _instance = new ThreadSafeSingleton(); public static ThreadSafeSingleton Instance { get { return _instance; } } public ThreadSafeSingleton() { } }
https://github.com/ssukhpinder/DesignPatterns
ስፖንሰርነቶች እነዚህን የመሳሰሉ አዳዲስ ፕሮጀክቶችን መጠገን እና መገንባት እንድቀጥል ረድቶኛል።
🙏 Pay፣ Noticed ወይም ማናቸውንም የእኔን ፕሮጄክቶች የምትጠቀሚ ከሆነ፣ ትንሽ አስተዋጽዖ ማለት ብዙ ማለት ነው። በራሱ፣ ክፍት ምንጭ ሂሳቦቹን አይከፍልም። በአንተ እገዛ፣ ስራዬን መቀጠል ዘላቂ ሊሆን ይችላል፣ እናም እውነተኛ ስራ ለማግኘት መሄድ አያስፈልገኝም 😛።
የC# ማህበረሰብ አካል ስለሆኑ እናመሰግናለን!