در برنامه نویسی کامپیوتری، مقداردهی اولیهٔ تنبل به انگلیسی ( Lazy Initialization) یک الگو برای به تأخیر انداختن ساخت یک شیء میباشد، به طوری که محاسبه و ایجاد شیء مورد نظر تا زمانی که به آن شیء نیازی نباشد معوق میشود.
این الگو زمانی استفاده میشود که ساخت شیء از نظر هزینهٔ محاسبهگران میباشد و اجرای برنامه در گرو ساخته شدن آن شیء نمیباشد. بدین ترتیب برنامه روال عادی اجرای خود را با سرعت بیشتری طی میکند و تنها وقتی به ساختن آن شیء میپردازد که به طور مستقیم به آن نیازمند بشود.
برای مثال تا وقتی که در برنامه نیاز به ارتباط به پایگاه دادهها نداریم شیء اتصال دهنده به پایگاه دادهها را نمیسازیم و از هزینههای محاسباتی ساخت چنین شیء ای اجتناب میکنیم، ولی به محض اینکه در این برنامه خواستیم به پایگاه دادهها متصل بشویم، برنامهٔ ما شیء اتصال را ساخته و از آن استفاده میکند.
معمولاً برای پیادهسازی این الگو از یک متغیر کمکی استفاده میکنند که میتواند ۲ حالت به خود بگیرد. حالت صفر به این معنا میباشد که پروسهٔ ساخت شیء هنوز رخ نداده و حالت 1 یعنی این که این پروسه اجرا شده و شیء قبلاً ساخته شده. هر بار که برنامه به شیء مورد نظر ارجاع میدهد، با چک کردن این متغیر کمکی میفهمیم که آیا شئ تا آلان ساخته شده یا نه.
اگر شیء ساخته شده بود که میتوان از همان برای ادامهٔ اجرای برنامه استفاده کنیم، در غیر این صورت باید ابتدا شئ را ساخته و مقدار دهی کرده و سپس مقدار متغیر کمکی را برابر یک قرار دهیم.
در مبحث الگوهای طراحی مهندسی نرمافزار ، دیزاین پترن مقداردهی تنبل معمولاً به کمک الگوی متد کارخانه می تواند سه روش و سه ایده ی کلی را به ما بدهد:
- استفاده از الگوی متد کارخانه برای ایجاد یک نمونه از یک کلاس
- ذخیره کردن نمونههای ساخته شده از آن کلاس در یک آرایه انجمنی (map). بدین ترتیب هر وقت که آن شیء را بخواهیم بتوانیم به کمک مشخصاتش از map آن را بدست آوریم.
- استفاده از تکنیک مقدار دهی اولیه کاهلانه برای ساخت شی برای اولین بار.
در ادامه دو مثال از این دیزاین پترن می آوریم که مثال اول از php و مثال دوم از جاوا می باشد:
در مثال زیر که به زبان php نوشته شده است از این الگو (Lazy Initialization) استفاده کرده ایم:
header('Content-type:text/plain; charset=utf-8');
class Fruit {
private $type;
private static $types = array();
private function __construct($type) {
$this->type = $type;
}
public static function getFruit($type) {
// Lazy initialization takes place here
if (!isset(self::$types[$type])) {
self::$types[$type] = new Fruit($type);
}
return self::$types[$type];
}
public static function printCurrentTypes() {
echo 'Number of instances made: ' . count(self::$types) . "\n";
foreach (array_keys(self::$types) as $key) {
echo "$key\n";
}
echo "\n";
}
}
Fruit::getFruit('Apple');
Fruit::printCurrentTypes();
Fruit::getFruit('Banana');
Fruit::printCurrentTypes();
Fruit::getFruit('Apple');
Fruit::printCurrentTypes();
/*
OUTPUT:
Number of instances made: 1
Apple
Number of instances made: 2
Apple
Banana
Number of instances made: 2
Apple
Banana
*/
در مثال زیر که به زبان جاوا نوشته شده است از این الگو (Lazy Initialization) استفاده کرده ایم:
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public enum FRUIT_TYPE {
NONE,
APPLE,
BANANA,
}
class Program {
/**
* @param args
*/
public static void main(String[] args) {
Fruit.getFruitByTypeName(FRUIT_TYPE.BANANA);
Fruit.showAll();
Fruit.getFruitByTypeName(FRUIT_TYPE.APPLE);
Fruit.showAll();
Fruit.getFruitByTypeName(FRUIT_TYPE.BANANA);
Fruit.showAll();
}
}
public class Fruit {
private static Map<FRUIT_TYPE, Fruit> types = new HashMap<>();
/**
* Using a private constructor to force the use of the factory method.
* @param type
*/
private Fruit(FRUIT_TYPE type) {
}
/**
* Lazy Factory method, gets the Fruit instance associated with a certain
* type. Instantiates new ones as needed.
* @param type Any allowed fruit type, e.g. APPLE
* @return The Fruit instance associated with that type.
*/
public static Fruit getFruitByTypeName(FRUIT_TYPE type) {
Fruit fruit;
// This has concurrency issues. Here the read to types is not synchronized,
// so types.put and types.containsKey might be called at the same time.
// Don't be surprised if the data is corrupted.
if (!types.containsKey(type)) {
// Lazy initialisation
fruit = new Fruit(type);
types.put(type, fruit);
} else {
// OK, it's available currently
fruit = types.get(type);
}
return fruit;
}
/**
* Lazy Factory method, gets the Fruit instance associated with a certain
* type. Instantiates new ones as needed. Uses double-checked locking
* pattern for using in highly concurrent environments.
* @param type Any allowed fruit type, e.g. APPLE
* @return The Fruit instance associated with that type.
*/
public static Fruit getFruitByTypeNameHighConcurrentVersion(FRUIT_TYPE type) {
if (!types.containsKey(type)) {
synchronized (types) {
// Check again, after having acquired the lock to make sure
// the instance was not created meanwhile by another thread
if (!types.containsKey(type)) {
// Lazy initialisation
types.put(type, new Fruit(type));
}
}
}
return types.get(type);
}
/**
* Displays all entered fruits.
*/
public static void showAll() {
if (types.size() > 0) {
System.out.println("Number of instances made = " + types.size());
for (Entry<FRUIT_TYPE, Fruit> entry : types.entrySet()) {
System.out.println(
Constants.firstLetterToUpper(entry.getKey().toString()));
}
System.out.println();
}
}
}
خروجی
Number of instances made = 1
Banana
Number of instances made = 2
Banana
Apple
Number of instances made = 2
Banana
Apple
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید