مشخصات مقاله
-
1714
-
0.0
-
7618
-
0
-
0
Design Patterns-الگوی Prototype
Prototype
در ادامه سری مقالات الگوهای طراحی، امروز با یکی دیگر از آنها، با نام Prototype آشنا خواهیم شد.
در صورتی که مقالات قبلی را مطالعه نکرده اید، از طریق لینک های زیر قابل دسترس هستند:
- Design Patterns
- Singleton Pattern
- Simple Factory Pattern
- Abstract Factory Pattern
- Factory Method Pattern
Prototype الگوی طراحی ای است که اشیاء را مجبور می کند تا در زمان ساخت، کپی یا شبیه سازی شوند.
آیا کپی شی هم مهم است؟
جواب ساده است. زمانی که اشیاء زیادی برای کار کردن نیاز باشد و ساخت آنها بسیار هزینه بر باشد، کپی کردن آنها می تواند به بهبود کارایی کمک کند.
از آنجا که بحث به کپی کردن کشیده شد، اجازه دهید کمی راجع به Shallow Copy و Deep Copy نیز صحبت کنیم.
Shallow Copy
همانطور که از نام آن مشخص است، این نوع کپی به صورت جزئی (Partial) و یا ناقص عمل میکند و هر refrence type ای از شی منبع، کپی نمی شود و همچنان، به همان محل از حافظه اشاره می کند.
در .NET با استفاده از متد MemberwiseClone این کار انجام می شود.
Deep Copy
در این نوع کپی نیز، همانطور که از نام آن مشخص است، یک کپی واقعی از تمام اعضاء شی منبع، حتی Refrence typeها، تهیه می شود. برای Refrence type ها، یک محل جدید از حافظه در Heap، اختصاص داده می شود تا کپی به درستی اجرا شود.
برای اجرای Deep Copy باید خودمان کدنویسی کنیم.
به بحث درمورد پیاده سازی الگو بازگردیم. فرض کنید یک کلاس Abstract به نام Vehicle داریم:
internal abstract class Vehicle
{
internal string VehicleType
{
get;
set;
}
internal string Brand
{
get;
set;
}
internal string Model
{
get;
set;
}
internal abstract void ShowDetails();
internal abstract Vehicle ShallowCopy();
internal abstract Vehicle DeepCopy();
internal ExtraInformation MoreInfo = new ExtraInformation();
} در صورت استفاده از این اینترفیس باید تمام Property ها را Override کنیم که به نوعی دوباره کاری است.
در اینجا کلاس Vehicle مانند یک Prototype عمل میکند. برای به تصویر کشیدن مفاهیم Deep Copy و Shallow Copy، یک کلاس با نام ExtraInformation اضافه می کنیم:
class ExtraInformation
{
internal string Cost { get;set;}
internal int Ratings { get;set;}
}پیاده سازی کلاس FouWheelar به شکل زیر خواهد بود:
internal class FourWheelar : Vehicle, ICloneable
{
internal override Vehicle ShallowCopy()
{
return this.MemberwiseClone() as Vehicle;
}
internal override Vehicle DeepCopy()
{
Vehicle vehicle = this.MemberwiseClone() as Vehicle;
vehicle.MoreInfo = new ExtraInformation();
vehicle.MoreInfo.Cost = this.MoreInfo.Cost;
vehicle.MoreInfo.Ratings = this.MoreInfo.Ratings;
return vehicle;
}
internal override void ShowDetails()
{
Console.WriteLine(string.Format("Vehicle Type: {0} \tBrand: {1} \tModel: {2} \tCost: {3} \tRatings: {4}", this.VehicleType, this.Brand, this.Model, this.MoreInfo.Cost,
this.MoreInfo.Ratings));
}
public object Clone()
{
return DeepCopy();
}
} همانطور که مشاهده می کنید، اینترفیس IClonable نیز پیاده سازی شده است. درواقع در این مثال به آن نیازی نداریم و فقط برای اعلام وجود آن را اضافه کرده ام. در این اینترفیس متدی با نام Clone وجود دارد که پس از فراخوانی، متد DeepCopy (که خودمان نوشته ایم) فراخوانی می شود.
برای مشاهده تنظیمات در سمت client:
static void Main()
{
Console.Title = "Prototype pattern demo";
FourWheelar car = new FourWheelar();
car.VehicleType = "Car";
car.Brand = "Maruti";
car.Model = "Swift";
car.MoreInfo.Cost = "6.5 Lakhs INR";
car.MoreInfo.Ratings = 2;
FourWheelar truck = car.ShallowCopy() as FourWheelar;
truck.VehicleType = "Truck";
truck.Brand = "Tata";
truck.Model = "ACE";
truck.MoreInfo.Cost = "4.5 Lakhs INR";
truck.MoreInfo.Ratings = 3;
Console.WriteLine("******************************Shallow Copy******************************");
Console.WriteLine("Origional Object:");
car.ShowDetails();
Console.WriteLine();
Console.WriteLine("Shallow Cloned Object:");
truck.ShowDetails();
} خروجی:
همانطور که مشاهده میکنید، زمانی که Cost و Rating را در شی موردنظر تغییر می دهیم، شی اصلی نیز تغییر می کند. دلیل این امر این است که شی کپی شده هم همان refrence های منبع را دارد.
و برای Deep Copy:
static void Main()
{
Console.Title = "Prototype pattern demo";
FourWheelar car = new FourWheelar();
car.VehicleType = "Car";
car.Brand = "Maruti";
car.Model = "Swift";
car.MoreInfo.Cost = "6.5 Lakhs INR";
car.MoreInfo.Ratings = 2;
FourWheelar truckNew = car.Clone() as FourWheelar;
truckNew.VehicleType = "Truck";
truckNew.Brand = "Tata";
truckNew.Model = "ACE";
truckNew.MoreInfo.Cost = "4.5 Lakhs INR";
truckNew.MoreInfo.Ratings = 3;
Console.WriteLine("******************************Deep Copy******************************");
Console.WriteLine("Origional Object:");
car.ShowDetails();
Console.WriteLine();
Console.WriteLine("Deep Cloned Object:");
truckNew.ShowDetails();
} خروجی:
همانطور که مشاهده میکنید، زمانی که cost و rating شی مورد نظر را تغییر می دهیم، شی اصلی تغییر نمی کند. چرا که شی کپی شده Refrence های جدیدی دارد.