انواع دیزاین پترن ها در #C (بخش سوم)
انواع دیزاین پترن ها در C# (بخش سوم)
با سلام.
تا به الان ما 10 نوع از دیزاین پترن ها در سی شارپ را برای شما عزیزان معرفی کردیم. در این مقاله و مقاله های بعد نیز به انواع دیگر می پردازیم. حال برای بهتر متوجه شدن این مقاله و مقالات بعد ابتدا مطالب زیر را بخوانید:
-
الگوهای طراحی Design Pattern
-
انواع دیزاین پترن ها در #C (بخش اول)
-
انواع دیزاین پترن ها در #C (بخش دوم)
دیزاین پترن ها در سی شارپ C#
انواع دیزاین پترن ها در C# (بخش سوم)
با سلام.
تا به الان ما 10 نوع از دیزاین پترن ها در سی شارپ را برای شما عزیزان معرفی کردیم. در این مقاله و مقاله های بعد نیز به انواع دیگر می پردازیم. حال برای بهتر متوجه شدن این مقاله و مقالات بعد ابتدا مطالب زیر را بخوانید:
-
الگوهای طراحی Design Pattern
-
انواع دیزاین پترن ها در #C (بخش اول)
-
انواع دیزاین پترن ها در #C (بخش دوم)
دیزاین پترن ها در سی شارپ C#
-
دیزاین پترن Flyweight | Flyweight Design Pattern – C#
الگوی Flyweight برای کاهش تعداد اشیاء ایجاد شده، کاهش حافظه و استفاده از منابع استفاده می شود. در نتیجه عملکرد آن را افزایش می دهد.
الگوی Flyweight سعی می کند تا با استفاده از ذخیره سازی اشیاء، بتواند در جاهای دیگر نیز از اشیاء موجود استفاده کند و هنگامی که هیچ شیء تطبیق یافت نشد، شی جدیدی ایجاد می شود.
این الگو دارای دو مفهوم داده های ذاتی و بیرونی است.
داده های ذاتی: داده های ذاتی در خواص اشیاء به اشتراک گذاشته می شوند. این اطلاعات بی ثبات است و به طور کلی بدون تغییر باقی می ماند، اگر تغییری رخ دهد، می تواند در میان تمام اشیائی که دارای Flyweight هستند، منعکس شود.
داده های بیرونی: در خارج از یک شیء Flyweight قرار می گیرند. از این رو می تواند وضعیتی باشد.
-
نمودار UML و پیاده سازی دیزاین پترن Flyweight
کلاس ها، اینترفیس ها و اشیاء در نمودار کلاس UML بالا به شرح زیر هستند:
Flyweight
یک رابط است که اعضای اشیاء Flyweight را تعریف می کند.
ConcreteFlyweight
یک کلاس که از کلاس Flyweight ارث میبرد.
UnsharedFlyweight
یک کلاس است که مشتق از کلاس Flyweight است (از کلاس Flyweight ارث میبرد) و امکان به اشتراک گذاری اطلاعات را فراهم می کند.
FlyweightFactory
یک کلاس است که اشاره به اشیاء موجود دارد. هنگامی که متد GetFlyweight از کلاینت فراخوانی می شود، این مراجع بررسی می شوند تا تعیین کنند که آیا یک Flyweight مناسب در حال حاضر وجود دارد یا خیر. اگر وجود داشته باشد که آن را بازمی گرداند. در غیر این صورت یک شی جدید ایجاد می شود.
public class FlyweightFactory
{
private Hashtable _flyweights = new Hashtable();
public Flyweight GetFlyweight(string key)
{
if (_flyweights.Contains(key))
{
return _flyweights[key] as Flyweight;
}
else
{
ConcreteFlyweight newFlyweight = new ConcreteFlyweight();
// Set properties of new flyweight here.
_flyweights.Add(key, newFlyweight);
return newFlyweight;
}
}
}
public interface Flyweight
{
void StatefulOperation(object o);
}
public class ConcreteFlyweight : Flyweight
{
public void StatefulOperation(object o)
{
Console.WriteLine(o);
}
}
public class UnsharedFlyweight : Flyweight
{
private object _state;
public void StatefulOperation(object o)
{
_state = o;
Console.WriteLine(o);
}
}
مثال:
کلاس ها، اینترفیس ها و اشیاء در تصویر بالا به شرح زیر هستند:
- ShapeObjectFactory- FlyweightFactory class.
- IShape - Flyweight interface.
- Circle & Rectabgle - ConcreteFlyweight class.
///
/// The 'Flyweight' interface
///
interface IShape
{
void Print();
}
///
/// A 'ConcreteFlyweight' class
///
class Rectangle : IShape
{
public void Print()
{
Console.WriteLine("Printing Rectangle");
}
}
///
/// A 'ConcreteFlyweight' class
///
class Circle : IShape
{
public void Print()
{
Console.WriteLine("Printing Circle");
}
}
///
/// The 'FlyweightFactory' class
///
class ShapeObjectFactory
{
Dictionary shapes = new Dictionary();
public int TotalObjectsCreated
{
get { return shapes.Count; }
}
public IShape GetShape(string ShapeName)
{
IShape shape = null;
if (shapes.ContainsKey(ShapeName))
{
shape = shapes[ShapeName];
}
else
{
switch (ShapeName)
{
case "Rectangle":
shape = new Rectangle();
shapes.Add("Rectangle", shape);
break;
case "Circle":
shape = new Circle();
shapes.Add("Circle", shape);
break;
default:
throw new Exception("Factory cannot create the object specified");
}
}
return shape;
}
}
class Program
{
static void Main(string[] args)
{
ShapeObjectFactory sof = new ShapeObjectFactory();
IShape shape = sof.GetShape("Rectangle");
shape.Print();
shape = sof.GetShape("Rectangle");
shape.Print();
shape = sof.GetShape("Rectangle");
shape.Print();
shape = sof.GetShape("Circle");
shape.Print();
shape = sof.GetShape("Circle");
shape.Print();
shape = sof.GetShape("Circle");
shape.Print();
int NumObjs = sof.TotalObjectsCreated;
Console.WriteLine("\nTotal No of Objects created = {0}", NumObjs);
Console.ReadKey();
}
}
خروجی کد بالا:
-
دیزاین پترن Proxy | Proxy Design Pattern – C#
الگوی طراحی پروکسی برای ارائه یک شیء جایگزین به سایر شیء ها مورداستفاده قرار می گیرد.
الگوی پروکسی شامل یک کلاس است که به نام کلاس Proxy شناخته می شود که نشان دهنده عملکرد کلاس دیگری است.
-
نمودار UML و پیاده سازی دیزاین پترن Proxy
کلاس ها، اینترفیس ها و اشیاء در نمودار کلاس UML بالا به شرح زیر هستند:
Subject
یک رابط کاربری است که توسط کلاس RealSubject و Proxy اجرا می شود.
RealSubject
یک کلاس که ما می خواهیم با استفاده از کلاس پروکسی کارهای کارآمد تر انجام دهیم.
Proxy
یک کلاس است که نمونه از کلاس RealSubject را نگه می دارد و می تواند در صورت نیاز به اعضای کلاس RealSubject دسترسی پیدا کند.
public interface Subject
{
void PerformAction();
}
public class RealSubject : Subject
{
public void PerformAction()
{
Console.WriteLine("RealSubject action performed.");
}
}
public class Proxy : Subject
{
private RealSubject _realSubject;
public void PerformAction()
{
if (_realSubject == null)
_realSubject = new RealSubject();
_realSubject.PerformAction();
}
}
مثال:
کلاس ها، اینترفیس ها و اشیاء در تصویر بالا به شرح زیر هستند:
- IClient- Subject Interface.
- RealClient - RealSubject Class.
- ProxyClient - Proxy Class.
///
/// The 'Subject interface
///
public interface IClient
{
string GetData();
}
///
/// The 'RealSubject' class
///
public class RealClient : IClient
{
string Data;
public RealClient()
{
Console.WriteLine("Real Client: Initialized");
Data = "Dot Net Tricks";
}
public string GetData()
{
return Data;
}
}
///
/// The 'Proxy Object' class
///
public class ProxyClient : IClient
{
RealClient client = new RealClient();
public ProxyClient()
{
Console.WriteLine("ProxyClient: Initialized");
}
public string GetData()
{
return client.GetData();
}
}
///
/// Proxy Pattern Demo
///
class Program
{
static void Main(string[] args)
{
ProxyClient proxy = new ProxyClient();
Console.WriteLine("Data from Proxy Client = {0}", proxy.GetData());
Console.ReadKey();
}
}
خروجی کد بالا:
-
دیزاین پترن Chain of Responsibility | Chain of Responsibility Design Pattern – C#
همانطور که از نام پترن Chain Of Responsibility مشخص است، این پترن تعدادی شی دریافت کننده برای درخواستی را میسازد. در این پترن کلاسهای دریافت کننده و درخواست کننده بر اساس نوع درخواست از یکدیگر جدا میشوند.
در این الگو، معمولا هر گیرنده (handler) حاوی مرجع به گیرنده دیگری است. اگر یک گیرنده نمی تواند درخواست را انجام دهد، آن را به گیرنده بعدی و غیره منتقل می کند.
-
نمودار UML و پیاده سازی دیزاین پترن Chain of Responsibility
کلاس ها، اینترفیس ها و اشیاء در نمودار کلاس UML بالا به شرح زیر هستند:
Client
یک کلاس که درخواست را تولید می کند و به Chain of Responsibility انتقال می دهد.
Handler
دارای یک روش انتزاعی abstract است که باید توسط کلاس های خاص برای رسیدگی به درخواست و یا انتقال آن به شی بعدی در pipeline اجرا شود.
ConcreteHandlerA & ConcreteHandlerB
قابلیت انجام بعضی درخواستها و انتقال به مورد بعدی
public abstract class Handler
{
protected Handler _successor;
public abstract void HandleRequest(int request);
public void SetSuccessor(Handler successor)
{
_successor = successor;
}
}
public class ConcreteHandlerA : Handler
{
public override void HandleRequest(int request)
{
if (request == 1)
Console.WriteLine("Handled by ConcreteHandlerA");
else if (_successor != null)
_successor.HandleRequest(request);
}
}
public class ConcreteHandlerB : Handler
{
public override void HandleRequest(int request)
{
if (request > 10)
Console.WriteLine("Handled by ConcreteHandlerB");
else if (_successor != null)
_successor.HandleRequest(request);
}
}
مثال:
کلاس ها، اینترفیس ها و اشیاء در تصویر بالا به شرح زیر هستند:
- Approver- Handler abstract class.
- Clerk, Assistant Manager & Manager - ConcreteHandler classes.
- Loan & LoanEventArgs - These classes are used for internal processing and holds request details.
// Loan event argument holds Loan info
public class LoanEventArgs : EventArgs
{
internal Loan Loan { get; set; }
}
///
/// The 'Handler' abstract class
///
abstract class Approver
{
// Loan event
public EventHandler Loan;
// Loan event handler
public abstract void LoanHandler(object sender, LoanEventArgs e);
// Constructor
public Approver()
{
Loan += LoanHandler;
}
public void ProcessRequest(Loan loan)
{
OnLoan(new LoanEventArgs { Loan = loan });
}
// Invoke the Loan event
public virtual void OnLoan(LoanEventArgs e)
{
if (Loan != null)
{
Loan(this, e);
}
}
// Sets or gets the next approver
public Approver Successor { get; set; }
}
///
/// The 'ConcreteHandler' class
///
class Clerk : Approver
{
public override void LoanHandler(object sender, LoanEventArgs e)
{
if (e.Loan.Amount < 25000.0)
{
Console.WriteLine("{0} approved request# {1}",
this.GetType().Name, e.Loan.Number);
}
else if (Successor != null)
{
Successor.LoanHandler(this, e);
}
}
}
///
/// The 'ConcreteHandler' class
///
class AssistantManager : Approver
{
public override void LoanHandler(object sender, LoanEventArgs e)
{
if (e.Loan.Amount < 45000.0)
{
Console.WriteLine("{0} approved request# {1}",
this.GetType().Name, e.Loan.Number);
}
else if (Successor != null)
{
Successor.LoanHandler(this, e);
}
}
}
///
/// The 'ConcreteHandler' clas
///
class Manager : Approver
{
public override void LoanHandler(object sender, LoanEventArgs e)
{
if (e.Loan.Amount < 100000.0)
{
Console.WriteLine("{0} approved request# {1}",
sender.GetType().Name, e.Loan.Number);
}
else if (Successor != null)
{
Successor.LoanHandler(this, e);
}
else
{
Console.WriteLine(
"Request# {0} requires an executive meeting!",
e.Loan.Number);
}
}
}
///
/// Class that holds request details
///
class Loan
{
public double Amount { get; set; }
public string Purpose { get; set; }
public int Number { get; set; }
}
///
/// ChainOfResponsibility Pattern Demo
///
class Program
{
static void Main(string[] args)
{
// Setup Chain of Responsibility
Approver rohit = new Clerk();
Approver rahul = new AssistantManager();
Approver manoj = new Manager();
rohit.Successor = rahul;
rahul.Successor = manoj;
// Generate and process loan requests
var loan = new Loan { Number = 2034, Amount = 24000.00, Purpose = "Laptop Loan" };
rohit.ProcessRequest(loan);
loan = new Loan { Number = 2035, Amount = 42000.10, Purpose = "Bike Loan" };
rohit.ProcessRequest(loan);
loan = new Loan { Number = 2036, Amount = 156200.00, Purpose = "House Loan" };
rohit.ProcessRequest(loan);
// Wait for user
Console.ReadKey();
}
}
خروجی کد بالا:
-
دیزاین پترن Command | Command Design Pattern – C#
Command پترن نوعی پترن دیتا محور است. یک درخواست(Request) در قالب یک کلاس به عنوان دستور(Command) قرار میگیرد. درخواست به کلاس دیگری که آن را کلاس فراخوانی (invoker class) نامگذاری میکنیم، فرستاده میشود. Invoker class به دنبال شی میگردد که درخواست فرستاده شده را پاسخ دهد و آن را اجرا کند.
-
نمودار UML و پیاده سازی دیزاین پترن Command
کلاس ها، اینترفیس ها و اشیاء در نمودار کلاس UML بالا به شرح زیر هستند:
Client
یک کلاس است که شیء Command را ایجاد و اجرا می کند.
Invoker
از Command خواست می کند تا عملیات را انجام دهد.
Command
یک رابط است که عمل Execute را مشخص می کند.
ConcreteCommand
یک کلاس است که عملیات Execute را با اعمال عملیات (ها) در گیرنده پیاده سازی می کند.
Receiver
یک کلاس است که عمل مربوط به درخواست را انجام می دهد.
public class Client
{
public void RunCommand()
{
Invoker invoker = new Invoker();
Receiver receiver = new Receiver();
ConcreteCommand command = new ConcreteCommand(receiver);
command.Parameter = "Dot Net Tricks !!";
invoker.Command = command;
invoker.ExecuteCommand();
}
}
public class Receiver
{
public void Action(string message)
{
Console.WriteLine("Action called with message: {0}", message);
}
}
public class Invoker
{
public ICommand Command { get; set; }
public void ExecuteCommand()
{
Command.Execute();
}
}
public interface ICommand
{
void Execute();
}
public class ConcreteCommand : ICommand
{
protected Receiver _receiver;
public string Parameter { get; set; }
public ConcreteCommand(Receiver receiver)
{
_receiver = receiver;
}
public void Execute()
{
_receiver.Action(Parameter);
}
}
مثال:
کلاس ها، اینترفیس ها و اشیاء در تصویر بالا به شرح زیر هستند:
- Switch- Invoker class.
- ICommand - Command interface.
- FlipUpCommand and FlipDownCommand - Concrete Command classes.
- Light - Receiver class.
///
/// The 'Command' interface
///
public interface ICommand
{
void Execute();
}
///
/// The 'Invoker' class
///
public class Switch
{
private List _commands = new List();
public void StoreAndExecute(ICommand command)
{
_commands.Add(command);
command.Execute();
}
}
///
/// The 'Receiver' class
///
public class Light
{
public void TurnOn()
{
Console.WriteLine("The light is on");
}
public void TurnOff()
{
Console.WriteLine("The light is off");
}
}
///
/// The Command for turning on the light - ConcreteCommand #1
///
public class FlipUpCommand : ICommand
{
private Light _light;
public FlipUpCommand(Light light)
{
_light = light;
}
public void Execute()
{
_light.TurnOn();
}
}
///
/// The Command for turning off the light - ConcreteCommand #2
///
public class FlipDownCommand : ICommand
{
private Light _light;
public FlipDownCommand(Light light)
{
_light = light;
}
public void Execute()
{
_light.TurnOff();
}
}
///
/// Command Pattern Demo
///
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter Commands (ON/OFF) : ");
string cmd = Console.ReadLine();
Light lamp = new Light();
ICommand switchUp = new FlipUpCommand(lamp);
ICommand switchDown = new FlipDownCommand(lamp);
Switch s = new Switch();
if (cmd == "ON")
{
s.StoreAndExecute(switchUp);
}
else if (cmd == "OFF")
{
s.StoreAndExecute(switchDown);
}
else
{
Console.WriteLine("Command \"ON\" or \"OFF\" is required.");
}
Console.ReadKey();
}
}
خروجی کد بالا:
-
دیزاین پترن Interpreter | Interpreter Design Pattern – C#
دیزاین پترن Interpreter از مجموعهای قوانین تشکیل شده که بر اساس آن قوانین، یک خروجی (در دستور زبان معنی جمله و در شی گرایی میتوان True یا False باشد) تولید میشود.
این الگو دستورالعمل هایی را که در دستور زبان یا نشانه های زبان نوشته شده اند را ارزیابی می کند. این الگو در کامپایلرها و یا تجزیه کننده ها استفاده می شود.
-
نمودار UML و پیاده سازی دیزاین پترن Interpreter
کلاس ها، اینترفیس ها و اشیاء در نمودار کلاس UML بالا به شرح زیر هستند:
Client
یک کلاس است که درخت دستور abstract را برای مجموعه ای از دستورالعمل ها در گرامر داده شده ایجاد می کند. این درخت با کمک نمونه هایی از کلاس های NonTerminalExpression و TerminalExpression ایجاد می شود.
Context
یک کلاس که حاوی اطلاعات (ورودی و خروجی) است که توسط مترجم استفاده می شود.
Expression
یک رابط است که عملیات Interpret را تعریف می کند که باید توسط هر زیر کلاس اجرا شود.
NonTerminal
یک کلاس است که Expression را اجرا می کند. این می تواند نمونه های دیگری از Expression باشد.
Terminal
یک کلاس است که Expression را اجرا می کند.
public class Client
{
public void BuildAndInterpretCommands()
{
Context context = new Context("Dot Net context");
NonterminalExpression root = new NonterminalExpression();
root.Expression1 = new TerminalExpression();
root.Expression2 = new TerminalExpression();
root.Interpret(context);
}
}
public class Context
{
public string Name { get; set; }
public Context(string name)
{
Name = name;
}
}
public interface IExpression
{
void Interpret(Context context);
}
public class TerminalExpression : IExpression
{
public void Interpret(Context context)
{
Console.WriteLine("Terminal for {0}.", context.Name);
}
}
public class NonterminalExpression : IExpression
{
public IExpression Expression1 { get; set; }
public IExpression Expression2 { get; set; }
public void Interpret(Context context)
{
Console.WriteLine("Nonterminal for {0}.", context.Name);
Expression1.Interpret(context);
Expression2.Interpret(context);
}
}
"منتشر شده در سایت ABLY"