Service jako vzor prototype

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
h4kuna
Backer | 740
+
0
-

Zdravím, chtěl bych se zeptat jak pomocí neonu zrealizuju návrhový vzor prototype ?

Chci vždy dostat klon připraveného objektu, ukázka:

<?php
$obj1 = $this->context->prototype;
$obj2 = $this->context->prototype;
dump($c === $c2)//FALSE
?>

Editoval h4kuna (10. 10. 2012 19:50)

Filip Procházka
Moderator | 4668
+
0
-

Jednoduchá varianta:

$obj1 = clone $this->context->prototype;

Složitější varianta:

class FooProvider extends Nette\Object
{
	private $foo;
	public function __construct(Foo $foo)
	{
		$this->foo = $foo;
	}
	public function get()
	{
		return clone $this->foo;
	}
}
services:
	fooProvider: FooProvider(Foo())
class MyPresenter extends BasePresenter
{
	private $fooProvider;
	public function injectFooProvider(FooProvider $fooProvider)
	{
		$this->fooProvider = $fooProvider;
	}

	public function actionDefault()
	{
		$foo = $this->fooProvider->get();
	}
}
h4kuna
Backer | 740
+
0
-

Děkuji složitější varianta je to co potřebuji. Spíše jsem doufal že jsem přehlédl nějaké nastavení pro neon. Například jako je blok services: nebo factories: tak by mohl být prototypes:?


He he :) jak elegantně jsi mi naznačil abych na $this->context zapomněl :D

Editoval h4kuna (10. 10. 2012 20:21)

Filip Procházka
Moderator | 4668
+
0
-

Prototype je natolik specifický „problém“ že nemá význam něco takového mít jako výchozí funkčnost. Já to třeba ještě nepotřeboval.

Každopádně můžeš udělat velice snadno CompilerExtension a publikovat ho jako addon :)


;)

gawan
Člen | 110
+
0
-

@HosipLan a nie je na toto práve factory? Ja mám napríklad na jednej stránke štyri zoznamy článkov, každý iný filter. A mám napr. triedu „Articles“ aký je teda dnes best practice? Použiť factory „->context->createArticles()“ alebo urobiť takýto nejaký provider?

Editoval gawan (19. 10. 2012 12:07)

Filip Procházka
Moderator | 4668
+
0
-

Ne, prototype ti dělá tohle

private $articles;

public function getArticles()
{
	if ($this->articles === NULL) {
		$this->articles = new Articles($this->db);
	}
	return clone $this->articles;
}

A factory tohle

public function getArticles()
{
	return new Articles($this->db);
}
mkoubik
Člen | 728
+
0
-

A v čem je rozdíl (kromě rychlosti – nevolá se konstruktor)?

David Matějka
Moderator | 6445
+
0
-

prave v tom :) http://goo.gl/Rm7m6 „Používá se, když je vytváření instance třídy velmi časově náročné nebo nějak výrazně složité.“

Editoval matej21 (19. 10. 2012 14:49)

h4kuna
Backer | 740
+
0
-

Já to občas používám když mam Html::el(‚el‘) + nějaká nastavení tak pak si ho clonu něž abych použil factory, otázka je co rychlejší, neměřil jsem. Taky jsem to chtěl použít pro přípravu objektu Message, kde je potřeba klonovat Template, do kterého se vkládá Latte a teď si nepamatuju na čem jsem ztroskotal. Ale zrovinka tady kdyby se mi to podařilo vyladit, tak by to bylo odlehčení. Ono to nemusí být jen vytvoření instance, ale třeba ještě nějaká nastavení.

private $articles;

public function getArticles()
{
	if ($this->articles === NULL) {
		$this->articles = new Articles($this->db);
		$this->articles->foo();
	}
	return clone $this->articles;
}
h4kuna
Backer | 740
+
0
-

mkoubik napsal(a):

A v čem je rozdíl (kromě rychlosti – nevolá se konstruktor)?

Při prototype se nespouští instance, ale udělá se hluboká kopie a pak se vrací ukazatel na novou kopii. Takže k výsledkům nedocházíš stejným případně složitým výpočtem.

pekelnik
Člen | 462
+
0
-

Jen tak pro uplnost dodam, ze „heavy“ constructor je bad practice ;) klonovani pouzivam tam kde potrebuji slozity objekt vicekrat – napriklad proto ze jeden z nich hodlam nejak „znicit“ a potrebuji ten puvodni jeste na neco jineho…