الگوی نما
الگوی نما (فساد): یک الگوی ساختاری در الگوهای طراحی نرمافزار میباشد که معمولاً در برنامهنویسی شی گرا از آن استفاده میشود. نام آن برگرفته از شباهت آن به مشابه آن در معماری ساختمان نما (ساختمان) میباشد.
نما، شیءای است که یک رابط راحت برای دسترسی به قسمت بزرگ و پیچیدهای از کد میباشد. مثل کتابخانه کلاسها. فساد میتواند:
- استفاده از یک کتابخانه نرمافزاری را آسانتر کند، بفهمد و آن را تست کند. چرا که توابع راحتی برای عملیاتهای عادی دارد.
- به دلایل مشابهی، خواندن از کتابخانه را راحتتر و امکانپذیرتر میکند.
- کاهش وابستگی به کدهای خارجی مهمترین وظیفه یک کتابخانه داخلی است، چرا که بیشتر قسمتهای کد از نما استفاده میکنند، باعث تغییرپذیری بیشتر در طراحی سیستم میشود.
- بسته مجموعهای از رابطهای برنامه کاربری با طراحی ضعیف، تنها با یک رابط برنامه کاربری (API) که از طراحی خوبی برخوردار است.
معمولاً وقتی از الگوی طراحی نما استفاده میشود که سامانه از پیچیدگی زیادی برخوردار است یا فهمیدن آن دشوار است، به خاطر آن که تعداد زیادی از کلاسهای دارای وابستگی داخلی یا کلاسهایی که کد آنها در دسترس نباشد وجود داشته باشند. این الگو پیچیدگی یک سامانه بزرگ را مخفی کرده و یک رابط ساده برای مشتری فراهم میکند. معمولاً دارای یک کلاس پوشهبندی ساده است که مجموعهای از عضوهای مورد نیاز مشتری در آن وجود دارند. این اعضا به جای مشتری نما، به سامانه دسترسی دارند و نحوه پیادهسازی را مخفی میکنند.
استفاده
معمولاً وقتی که رابط دسترسی راحتتر به یک شیء در سطح پایینتر نیاز باشد از فساد استفاده میشود. همچنین زمانه که پوشهبند (wrapper) نیاز است تا یک رابط خاصی را رعایت کند و رفتار چندوجهی (polymorphic) را رعایت کند از آداپتور میتوان استفاده کرد. توسط دکوراتور میتوان رفتار یک واسط را در زمان اجرا تغییر داد.
الگو | هدف |
---|---|
آداپتور | تغییر یک رابط به رابط دیگر جهت برآوردن انتظار مشتری |
دکوراتور | به صورت پویا (داینامیک) با تغییر کد ویژگیهای جدیدی به رابط کاربری اضافه میکند. |
نما | یک رابط راحت ایجاد ارائه میکند. |
معمولاً در مواقعی از الگوی نما استفاده میشود که:
- به یک رابط راحت برای دسترسی به یک سامانه پیچیده نیاز است.
- سامانهای بسیار پیچیده است یا فهمیدن آن دشوار است.
- در یک نرمافزار لایهبندی شده، برای دسترسی به هر لایه، یک ورودی مجزا نیاز باشد و یا
- انتزاع و پیادهسازی یک بخش از سامانه (subsystem) به شدت به یکدیگر وابسته باشند.
ساختار
- Facade (نما)
- نما بستههای ۱ تا ۳ را از بقیه برنامه جدا میکند.
- Clients (مشتریان)
- اشیاای که توسط الگوی نما به منابع دسترسی پیدا میکنند.
مثال
این مثال خلاصه از چگونگی ارتباط یک مشتری با یک نما در یک سامانه پیچیده است. (مشتری: کاربر، نما: کامپیوتر، سامانه: سختافزار کامپیوتر)
C
پیادهسازی
namespace DesignPattern.Facade
{
class SubsystemA
{
public string OperationA1()
{
return "Subsystem A, Method A1\n";
}
public string OperationA2()
{
return "Subsystem A, Method A2\n";
}
}
class SubsystemB
{
public string OperationB1()
{
return "Subsystem B, Method B1\n";
}
public string OperationB2()
{
return "Subsystem B, Method B2\n";
}
}
class SubsystemC
{
public string OperationC1()
{
return "Subsystem C, Method C1\n";
}
public string OperationC2()
{
return "Subsystem C, Method C2\n";
}
}
public class Facade
{
private readonly SubsystemA a = new SubsystemA();
private readonly SubsystemB b = new SubsystemB();
private readonly SubsystemC c = new SubsystemC();
public void Operation1()
{
Console.WriteLine("Operation 1\n" +
a.OperationA1() +
b.OperationB1() +
c.OperationC1());
}
public void Operation2()
{
Console.WriteLine("Operation 2\n" +
a.OperationA2() +
b.OperationB2() +
c.OperationC2());
}
}
}
نمونه کد
namespace DesignPattern.Facade.Sample
{
// The 'Subsystem ClassA' class
class CarModel
{
public void SetModel()
{
Console.WriteLine(" CarModel - SetModel");
}
}
/// <summary>
/// The 'Subsystem ClassB' class
/// </summary>
class CarEngine
{
public void SetEngine()
{
Console.WriteLine(" CarEngine - SetEngine");
}
}
// The 'Subsystem ClassC' class
class CarBody
{
public void SetBody()
{
Console.WriteLine(" CarBody - SetBody");
}
}
// The 'Subsystem ClassD' class
class CarAccessories
{
public void SetAccessories()
{
Console.WriteLine(" CarAccessories - SetAccessories");
}
}
// The 'Facade' class
public class CarFacade
{
private readonly CarAccessories accessories;
private readonly CarBody body;
private readonly CarEngine engine;
private readonly CarModel model;
public CarFacade()
{
accessories = new CarAccessories();
body = new CarBody();
engine = new CarEngine();
model = new CarModel();
}
public void CreateCompleteCar()
{
Console.WriteLine("******** Creating a Car **********");
model.SetModel();
engine.SetEngine();
body.SetBody();
accessories.SetAccessories();
Console.WriteLine("******** Car creation is completed. **********");
}
}
// Facade pattern demo
class Program
{
static void Main(string[] args)
{
var facade = new CarFacade();
facade.CreateCompleteCar();
Console.ReadKey();
}
}
}
جاوا
/* Complex parts */
class CPU {
public void freeze() { ... }
public void jump(long position) { ... }
public void execute() { ... }
}
class HardDrive {
public byte[] read(long lba, int size) { ... }
}
class Memory {
public void load(long position, byte[] data) { ... }
}
/* Facade */
class ComputerFacade {
private CPU processor;
private Memory ram;
private HardDrive hd;
public ComputerFacade() {
this.processor = new CPU();
this.ram = new Memory();
this.hd = new HardDrive();
}
public void start() {
processor.freeze();
ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE));
processor.jump(BOOT_ADDRESS);
processor.execute();
}
}
/* Client */
class You {
public static void main(String[] args) {
ComputerFacade computer = new ComputerFacade();
computer.start();
}
}
Ruby
# Complex Parts
class CPU
def freeze; end
def jump(position); end
def execute; end
end
class Memory
def load(position, data); end
end
class HardDrive
def read(lba, size); end
end
# Facade
class ComputerFacade
def initialize
@processor = CPU.new
@ram = Memory.new
@hd = HardDrive.new
end
def start
@processor.freeze
@ram.load(BOOT_ADDRESS, @hd.read(BOOT_SECTOR, SECTOR_SIZE))
@processor.jump(BOOT_ADDRESS)
@processor.execute
end
end
# Client
computer_facade = ComputerFacade.new
computer_facade.start
منابع
- ↑ Freeman, Eric; Freeman, Elisabeth; Sierra, Kathy; Bates, Bert (2004). Hendrickson, Mike; Loukides, Mike (eds.). "Head First Design Patterns" (paperback). 1. O'Reilly: 243, 252, 258, 260. ISBN 978-0-596-00712-6. Retrieved 2012-07-02.