الگوهای طراحی راه حل های اثبات شده ای برای مشکلات طراحی نرمافزار هستند. آنها به بهبود کیفیت کد، ارتقای قابلیت استفاده مجدد و افزایش قابلیت نگهداری کمک می کنند. ما از آنها برای صرفهجویی در زمان و تولید کد های با کیفیت، توسعهپذیر و انعطافپذیر استفاده میکنیم. در این مطلب قصد داریم الگوی طراحی Bridge را معرفی کنیم.
الگوی Bridge یک الگوی طراحی ساختاری(Structural) است که انتزاعات را از پیاده سازی ها جدا می کند تا بتوانند مستقل باشند. این الگو این امکان را میدهد که انعطاف پذیری و قابلیت جایگذینی بیشتر بین پیاده سازی های مختلف یک انتزاع وجود داشته باشد.
در این الگو، دو سلسله مراتب مجزا وجود دارد: یک سلسله مراتب انتزاعی و یک سلسله مراتب پیاده سازی. سلسله مراتب انتزاع، رابط(Interface) سطح بالایی را تعریف می کند که کد های کلاینت برای تعامل با انتزاع از آن استفاده می کنند، در حالی که سلسله مراتب پیاده سازی، موجودیت های عینی همان انتزاع را ارائه می دهد.
الگوی Bridge زمانی مفید است که چندین پیاده سازی از یک انتزاع وجود داشته باشد و ما بخواهیم آنها را در زمان اجرا تغییر دهیم، بدون اینکه روی کد کلاینت تأثیر بگذاریم. با جداسازی سلسله مراتب انتزاع و پیاده سازی، به کاهش وابستگی بین اجزاء کمک میشود و حفظ و اصلاح هر دو سلسله مراتب را به طور مستقل آسان تر می کند.
در ادامه مثالی از نحوه پیاده سازی الگوی Bridge در سی شارپ آمده است:
// Abstraction
public abstract class Shape
{
protected IRenderer renderer;
public Shape(IRenderer renderer)
{
this.renderer = renderer;
}
public abstract void Draw();
}
public class Circle : Shape
{
private float radius;
public Circle(IRenderer renderer, float radius) : base(renderer)
{
this.radius = radius;
}
public override void Draw()
{
renderer.RenderCircle(radius);
}
}
public class Square : Shape
{
private float side;
public Square(IRenderer renderer, float side) : base(renderer)
{
this.side = side;
}
public override void Draw()
{
renderer.RenderSquare(side);
}
}
// Implementation
public interface IRenderer
{
void RenderCircle(float radius);
void RenderSquare(float side);
}
// Concrete Implementation
public class VectorRenderer : IRenderer
{
public void RenderCircle(float radius)
{
Console.WriteLine($"Drawing a circle of radius {radius} using vector graphics.");
}
public void RenderSquare(float side)
{
Console.WriteLine($"Drawing a square of side {side} using vector graphics.");
}
}
// Concrete Implementation
public class RasterRenderer : IRenderer
{
public void RenderCircle(float radius)
{
Console.WriteLine($"Drawing a circle of radius {radius} using raster graphics.");
}
public void RenderSquare(float side)
{
Console.WriteLine($"Drawing a square of side {side} using raster graphics.");
}
}
// Client code
var vectorCircle = new Circle(new VectorRenderer(), 5);
vectorCircle.Draw(); // Output: Drawing a circle of radius 5 using vector graphics.
var rasterSquare = new Square(new RasterRenderer(), 10);
rasterSquare.Draw(); // Output: Drawing a square of side 10 using raster graphics.
در این مثال، کلاس Shape انتزاع است و دارای مشتقات Circle و Square است. رابط IRenderer بخش پیاده سازی است و دارای دو پیاده سازی اصلی VectorRenderer و RasterRenderer است. کلاس Shape یک شی IRenderer را در سازنده خود می گیرد و از آن برای اجرای دستور ترسیم شکل در پیاده سازی های مربوطه استفاده میکند. کد کلاینت می تواند اشکال مختلفی را با پیاده سازی های مختلف در زمان اجرا ایجاد کند، بدون اینکه نیاز به تغییر کد داشته باشد.
برای مطالعه سایر الگو های طراحی، میتوانید از لیست زیر استفاده کنید. همچنین یک مخزن کد در گیت هاب که شامل همهی الگو های طراحی میشود، برای شما قرار گرفته است.
من محمدرضا باباخانی هستم، توسعه دهنده نرم افزار. در اینجا تجربیات، نظرات و پیشنهادات خودم رو درباره تکنولوژی مینویسم. امیدوارم مطالبی که مینویسم بدردتون بخوره.
ثبت دیدگاه