کار این الگو در یک جمله این است که اگر متدی نتواند خروجی مناسبی را بدهد و به جای آن قرار باشد نال را برگشت دهد، به جای برگشت دادن نال، از یک شیء که هیچ رفتاری ندارد استفاده میکند و آن شیء را برمیگرداند تا در ادامه کد، بررسی نال بودن، یا خطای NPE رخ ندهد.
به عنوان مثال فرض کنید قرار است یک کاربر با نام کاربری Ali به سیستم وارد شود؛ در اینجا سه حالت وجود دارد:
- این کاربر یافت شده و اجازه دسترسی دارد.
- این کاربر یافت شده و اجازه دسترسی ندارد.
- این کاربر یافت نمیشود.
اگر در حالتیکه کاربر یافت نشود، بخواهیم نال برگردانیم، در ادامهی کد باید بررسی نال بودن و یا گاها انتظار خطای NPE را داشته باشیم؛ یا اینکه در عوض از الگوی شیء نال بهره ببریم.
بدون استفاده از الگو
در این مثال ابتدا کلاس یوزر را میسازیم:
public class User { public String Usernam { get; set; } public bool Authenticated { get; set; } }
public User GeUser(string uname) { if (uname == "Ali") { return new User() { Usernam = "Ali", Authenticated = true }; } else if (uname == "Reza") { return new User() { Usernam = "Reza", Authenticated = false }; } else { return null; } }
var userServices=new UserServices(); var user = userServices.GeUser("Ali"); if (user != null && user.Authenticated) { Console.WriteLine("You are Authorized"); }
استفاده از الگو
ابتدا یک کلاس جدید را با ارث بری از کلاس یوزر میسازیم:
public class NullUser:User { public NullUser() { Authenticated = false; } }
public User GeUser(string uname) { if (uname == "Ali") { return new User() { Usernam = "Ali", Authenticated = true }; } else if (uname == "Reza") { return new User() { Usernam = "Reza", Authenticated = false }; } return new NullUser(); }
var userServices=new UserServices(); var user = userServices.GeUser("xxx"); if (user.Authenticated) Console.WriteLine("You are Authorized");
یک نکته اضافه تر اینکه، در صورتی که قصد دارید متدی را در کلاس پدر تحریف کنید، بهتر است یک اینترفیس یا کلاس انتزاعی را تعریف و هر دو کلاس را از آن ارث بری کنید که برای مثال بالا میشود اینترفیس IUser و دو کلاس User و NullUser هم مشتقات آن.