**Բազմակի օգտագործման** նախագծման մոդելը նման է եզակի օգտագործման նախագծման մոդելին, որը թույլ է տալիս ստեղծել դասի միայն մեկ նմուշ։ Բազմակի օգտագործման մոդելն ընդլայնում է Եզակիի հնարավորությունները և թույլ է տալիս ունենալ անուններով հիշվող նմուշների մասիվ, ընդ որում, անունները հանդիսանում են նմուշների բանալի-արժեքները։

Մարդկանցից շատերը այն համարում են եզակի օգտագործման նախագծման մոդելի ձև։ Օրինակ բազմակի օգտագործման ձևանմուշը ԳօՖի գրքում միայն հանդես է գալիս որպես եզակի օգտագործման մոդելի մասնակի ձև, որը թույլ է տալիս ռեգիստրացնել եզակի օգտագործման մոդելները՝ այն ավելի ճկուն դարձնելու նպատակով։

Ընդհանուր հասկացողություններ
----------------------------

* Client - հայցող
* Instance - նմուշ
* Implementation - իրականացում
* Product - արգասիք

Նկարագրություն
--------------

Բազմակի օգտագործման նախագծման ձևանմուշը գլոբալ հասանելիություն է ապահովում միայն անուններով նմուշներ ունեցող դասի բոլոր նմուշներին։

Կառուցվածք
----------

Բազմակի օգտագործման նախագծման ձևանմուշի կառուցվածքըԲազմակի օգտագործման նախագծման ձևանմուշի կառուցվածքը

Օգտագործում
-----------

Առաջին հայացքից թվում է, թե բազմակի օգտագործումը ոչ ավելի է քան հեշ աղյուսակների օգտագործումով հասանելիությունը սինխրոնիզացնող մոդել, բայց այն երկու կարևոր տարբերություն ունի։ Առաջին հերթին բազմակի օգտագործումը հայցողներին թույլ չի տալիս mapping-ներ ավելացնել։ Երկրորդ հերթին բազմակի օգտագործումը երբեք `null` կամ դատարկ հղում չի վերադրաձնում։ Դրա փոխարեն այն ստեղծում և պահում է բազմակիի նմուշը նրա հետ կապված «բանալու» (անգլ.՝ key) հետ։ Նույն բանալիով հաջորդող կանչերի դեպքում կվերադարձվի իրական նմուշը։ Հեշ աղյուսակը միայն հանդիսանում է իրականացման դետալներից մեկը, բայց ոչ միակը։ Ձևանմուշը հեշտացնում է ծրագրային ապահովումից (անգլ.՝ application) ընդհանուր (անգլ.՝ shared) օբյեկտների դուրս բերումը։

Քանի որ ավազան օբյեկտը ստեղծվում է միայն մեկ անգամ՝ ասոցացված լինելով դասի (նմուշի փոխարեն), ապա բազմակի օգտագործումը պահում է իր հարթ վարքագիծը (անգլ.՝ behavior) և չի վերածվում ծառատիպ կառուցվածքի։

Բազմակի օգտագործման ձևանմուշը ունիկալ է նրանով, որ այն ապահովում է կենտրոնացված հասանելիություն մի ուղղությամբ (այսինքն բոլոր բանալիները գտնվում են միևնույն անվանատարածքում), որտեղ ամեն մի նմուշ ունի իր սեփական վիճակը։ Այսպիսով ձևանմուշը հանդիսանում է օյեկտները համակարգում ինդեքսավորումով պահող մոդել։ Բայց և այնպես, բազմակի օգտագործումը ունի սահմանափակ կիրառություն եզակի համակարգում՝ ի տարբերություն բազմաթիվ բաշխվածություն ունեցող համակարգերում (անգլ.՝ distributed systems)։

Թերություններ
-------------

Այս ձևանմուշը եզակի օգտագործման ձևանմուշի նման թեսթավորումը դարձնում է բավականին դժվար, քանի որ այն գլոբալ վիճակ է մտցնում ծրագրային ապահովվածության մեջ։

Բազմակի օգտագործման ձևանմուշը օբյեկտների վրա օգտագործում է գլոբալ հզոր հղումներ, որը որոշ ծրագրավորման լեզուներում կարող է բերել հիշողության կորստի (անգլ.՝ memory leaks)։

Օրինակներ
---------

Ահա պարզեցված օգտագործման օրինակներ մի շարք ծրագրավորման լեզուներով.

### Java

```
public class FooMultiton {
 private static final Map<Object, FooMultiton> instances = new HashMap<Object, FooMultiton>();

 private FooMultiton() {
 // no explicit implementation
 }

 public static synchronized FooMultiton getInstance(Object key) {

 // Our "per key" singleton
 FooMultiton instance = instances.get(key);
 
 if (instance == null) {
 // Lazily create instance
 instance = new FooMultiton();

 // Add it to map 
 instances.put(key, instance);
 }

 return instance;
 }

 // other fields and methods ...
}

```

### ActionScript 3.0

```
 import flash.utils.Dictionary;
 
 public class InternalModelLocator {
 private static var instances:Dictionary = new Dictionary();
 private static var allowCreation:boolean = false; 

 public function InternalModelLocator() {
 if(!allowCreation){
 throw new Error("Only one instance allowed to be created, and only with GetInstanceMethod"); 
 }
 }
 
 /\* module\_uuid can be a String --------
 In case of PureMVC "multitonKey" (this.multitonKey) can be used as unique key for multiple modules
 \*/
 public static function getInstance(module\_uuid:String):InternalModelLocator {
 var instance:InternalModelLocator = instances[module\_uuid];
 
 if (instance == null) {
 allowCreation = true; 
 instance = new InternalModelLocator();
 allowCreation = false;
 instances[module\_uuid] = instance;
 }
 return instance;
 }
 }

```

### C#

```
using System.Collections.Generic;
using System.Collections.Concurrent;

namespace MyApplication
{
 public class Multiton<T> where T : new() // generic multition.
 {
 private static readonly ConcurrentDictionary<object, T> \_instances = new ConcurrentDictionary<object, T>();

 private Multiton() { }

 public static T GetInstance(object key) 
 {
 return \_instances.GetOrAdd(key, (k) => new T());
 }
 }
}

```

Բազմակի օգտագործման ձևանմուշի բավականին պարզ օրինակ private կոնստրուկտորով և ստեղծված օբյեկներ ռեգիստրացնող մոդելով.

```
//IVSR: Multiton design pattern
namespace IVSR.DesignPatterns.Multiton
{
 public class Multiton
 {
 //read-only dictionary to track multitons
 private static IDictionary<int, Multiton> \_Tracker = new Dictionary<int, Multiton> { };

 private Multiton()
 {
 }

 public static Multiton GetInstance(int key)
 {
 //value to return
 Multiton item = null;
 
 //lock collection to prevent changes during operation
 lock (\_Tracker)
 { 
 //if value not found, create and add
 if(!\_Tracker.TryGetValue(key, out item))
 {
 item = new Multiton();

 //calculate next key
 int newIdent = \_Tracker.Keys.Max() + 1;

 //add item
 \_Tracker.Add(newIdent, item);
 }
 }
 return item;
 }
 }
}

```

### C++

Ճշգրտված իրականացումը StackOverflow կայքից.

```
#ifndef MULTITON\_H
#define MULTITON\_H

#include <map>
#include <string>

template <typename T, typename Key = std::string>
class Multiton
{
public:
 static void destroy()
 {
 for (typename std::map<Key, T\*>::const\_iterator it = instances.begin(); it != instances.end(); ++it)
 delete (\*it).second;
 instances.clear();
 }

 static T\* getPtr(const Key& key) {
 typename std::map<Key, T\*>::const\_iterator it = instances.find(key);

 if (it != instances.end()) {
 return (T\*)(it->second);
 }

 T\* instance = new T();
 instances[key] = instance;
 return instance;
 }

 static T& getRef(const Key& key) {
 return \*getPtr(key);
 }

protected:
 Multiton() {}
 ~Multiton() {}

private:
 Multiton(const Multiton&) {}
 Multiton& operator= (const Multiton&) { return \*this; }

 static std::map<Key, T\*> instances;
};

template <typename T, typename Key>
std::map<Key, T\*> Multiton<T, Key>::instances;

#endif

// example usage
class Foo : public Multiton<Foo> {};
Foo& foo1 = Foo::getRef("foobar");
Foo\* foo2 = Foo::getPtr("foobar");
Foo::destroy();

```

### PHP

```
<?php
// This example requires PHP 5.3+
abstract class Multiton {
    private static $instances = array();
    public static function getInstance() {
	// For non-complex construction arguments, you can just use the $arg as the key
		$key = get\_called\_class(). serialize(func\_get\_args());
		if (!isset(self::$instances[$key])) {
		// You can do this without the reflection class if you want to hard code the class constructor arguments
			$rc = new ReflectionClass(get\_called\_class());
			self::$instances[$key] = $rc->newInstanceArgs(func\_get\_args());
		}
		return self::$instances[$key];
    }
}

class Hello extends Multiton {
	public function \_\_construct($string = 'World') {
		echo "Hello $string\n";
	}
}

class GoodBye extends Multiton {
	public function \_\_construct($string = 'my', $string2 = 'darling') {
		echo "Goodbye $string $string2\n";
	}
}

$a = Hello::getInstance('World');
$b = Hello::getInstance('bob');
// $a !== $b

$c = Hello::getInstance('World');
// $a === $c

$d = GoodBye::getInstance();
$e = GoodBye::getInstance();
// $d === $e

$f = GoodBye::getInstance('your');
// $d !== $f

```

### Python

```
class A(object):
    def \_\_init\_\_(self, \*args, \*\*kw):
        pass

multiton = {}
a0 = multiton.setdefault('a0', A()) # get object by key, or create new and return it
a1 = multiton.setdefault('a1', A())
print multiton.get('a0')
print multiton.get('a1')

```

#### Դեկորատորների օգտագործում

```
def multiton(cls):
    instances = {}
    def getinstance(name):
        if name not in instances:
            instances[name] = cls()
        return instances[name]
    return getinstance

@multiton
class MyClass:
    ...

a=MyClass("MyClass0")
b=MyClass("MyClass0")
c=MyClass("MyClass1")
print a is b #True
print a is c #False

```

### Perl

```
use strict;
use warnings;

package MyClass {
 use Moose;

 has name => ( is => 'ro', isa => 'Str', required => 1 );
}

package Multiton { # version 5.14 package syntax
 my %\_objs;
 our $\_class = 'MyClass';

 sub set {
 my $self = shift;
 my ( $key, @args ) = @\_;
 die "key unspecifiied" unless defined $key;
 die "key is not a plain scalar" if ref($key);
 if ( exists $\_objs{$key} ) {
 $\_objs{$key};
 } else {
 $\_objs{$key} = $\_class->new(@args);
 }
 }

 sub get {
 my $self = shift;
 my $class = ref($self) || $self;
 $class->set(@\_);
 }

 sub delete {
 my $self = shift;
 for my $key (@\_) {
 delete $\_objs{$key};
 }
 }
}

my $a = Multiton->get( 'MyClassA' => ( name => 'Rover' ) );
my $b = Multiton->get( 'MyClassB' => ( name => 'Roger' ) );
my $c = Multiton->get('MyClassA');

print $a == $b ? 'true' : 'false', "\n"; # false
print $a == $c ? 'true' : 'false', "\n"; # true

```

Ծանոթագրություններ
------------------

1. ↑


|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * դ
* ք
* խ
Նախագծման ձևանմուշներ |
| --- |
|  |
| ԳօՖիձևանմուշներ | 

|  |  |
| --- | --- |
| Ստեղծող | Աբստրակտ ֆաբրիկա • Կառուցող • Ֆաբրիկային մեթոդ • Նախատիպ • Եզակի օգտագործման |
| Կառուցվածքային | Ադապտեր • Կամուրջ • Կազմող • Դեկորատոր • Ճակատ • Հարմարեցնող • Պրոքսի |
| Վարքագծային | Պարտականությունների շղթա • Հրաման • Թարգմանիչ • Իտերատոր • Միջնորդ • Պահպանող • Դիտորդ • Վիճակ • Մարտավարություն • Կաղապարային մեթոդ • Այցելող |

 |
|  |
| Ստեղծող ձևանմուշներ | Ծույլ բեռնում • Բազմակի օգտագործման • Օբյեկտների ավազան • Ռեսուրսի ստանալը ինիցիալիզացիա է |
|  |
| Կառուցվածքային ձևանմուշներ | Ճակատը հսկող • Մոդուլ |
|  |
| Համաձայնեցման ձևանմուշներ | Ակտիվ օբյեկտ • Հենվող • Մեկուսացում կրկնակի ստուգումով • Ասինքրոն կանչի մեթոդ • Պահպանվող կախոց • Ռեգիստրացնող • Կողպեքավորող • Մոնիտոր • Նախագործող • Ապագործող • Ընթերցողներ-գրողի կողպեք • Պլանավորման • Հոսքերի ավազանի • Հոսքերի լոկալ հիշողություն |
|  |
| Ճարտարապետական ձևանմուշներ | Ճակատը հսկող ձևանմուշ • Զավթող ձևանմուշ • ձևանմուշի ներկայացման վերահսկում • Բազմաշերտ • Հատկորոշում • Հրատարակող-ստորագրող • Մերկ օբյեկտներ • Ծառայության լոկատոր • Ակտիվ գրառման • Բազմության իդենտիֆիկացման • Data access object • Data transfer object |
|  |
| Այլ ձևանմուշներ | Կախվածության ներդնում • Mock օբյեկտ • Զրոյական օբյեկտ • Ծառայող • Թունելային տարատեսակի |

 |