- Въпросче?
12345
WT форуми -> Дъра-бъра -> Въпросче?
Създайте нова тема Напишете отговор 
Автор Съобщение
teroristd
Редовен
Редовен

Регистриран на: 18/02/2010 1:50 pm

Support: 80
Bonus: 172
Мнения: 1561
Мнение 18/05/2017 2:13 pm     Въпросче? Отговорете с цитат


Нека хипотетично си представим, че имам един обикновен клас в който, правя конекция към база данни. Да кажем имам втори клас с някави методи който е сингълтон и наследява конекцията.

Въпросът ми е ако използвам сингълтона в някакви други класове, винаги ли ще имам една и съща конекция, въпреки че тя самата не е сингълтон?

Съвсем грубо ще онагледя за да стане по-ясно какво имам в предвид.


class Connection {
    // Конекция към база данни
}

class Singleton extends Connection {
    // Някакви методи
}

class TestOne {
    $singleton = Singleton::getInstance();
}

class TestTwo {
    $singleton = Singleton::getInstance();
}
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
teroristd
Редовен
Редовен

Регистриран на: 18/02/2010 1:50 pm

Support: 80
Bonus: 172
Мнения: 1561
Мнение 25/05/2017 10:07 am      Отговорете с цитат


Явно никой не може да отговори на въпроса. Тогава ще попитам нещо друго. Твърди се че използването на singleton е лошо. Въпросът ми е как може да има само една инстанция на обекта без този обект да е singleton?
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
Fakeheal
Support
Support

Регистриран на: 17/04/2010 8:37 am

Support: 340
Bonus: 678
Мнения: 2556
Мнение 25/05/2017 12:52 pm      Отговорете с цитат


Трябва да пуснеш малко повече код от това, което си написал по-горе. Smile

А иначе сингълтона се смята за антипатърн. Нещо като глобалните променливи, които е препоръчително да не се използват. Нарушава single responsibility принципа. Също така прави кода tight coupled, което пречи на поддръжката на кода.

Може да погледнеш за dependency injection, много хора го дават като алтернатива и по-добър начин, ако се говори за code maintainability Smile
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение Изпрати мейла
teroristd
Редовен
Редовен

Регистриран на: 18/02/2010 1:50 pm

Support: 80
Bonus: 172
Мнения: 1561
Мнение 25/05/2017 1:34 pm      Отговорете с цитат


Fakeheal написа:
Трябва да пуснеш малко повече код от това, което си написал по-горе. Smile

А иначе сингълтона се смята за антипатърн. Нещо като глобалните променливи, които е препоръчително да не се използват. Нарушава single responsibility принципа. Също така прави кода tight coupled, което пречи на поддръжката на кода.

Може да погледнеш за dependency injection, много хора го дават като алтернатива и по-добър начин, ако се говори за code maintainability Smile


Разбира се dependency injection Smile . Само че той не е алтернатива на singleton, или може би аз го разбирам погрешно.


class Connection {

    // Конекция към база данни

}



class ModelOne {

    private $_connection;

    public function __construct(Connection $connection) {

        $this->_connection = $connection;

    }

}


class ModelTwo {

    private $_connection;

    public function __construct(Connection $connection) {

        $this->_connection = $connection;

    }

}


Поправи ме ако греша, но ето какво се случва в този примерен код за dependency injection. Да кажем имаме клас, който се грижи за създаването на обектите. В случая аз инжектирам Connection в два различни класа и съответно ще бъдат създадени два обекта, което пък значи че ще имам две конекции.

Ако класът Connection беше сингълтон щях да имам само една.
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
anonimen
Активен
Активен

Регистриран на: 11/06/2012 8:07 pm

Support: 141
Bonus: 281
Мнения: 1307
Мнение 25/05/2017 2:47 pm      Отговорете с цитат


Цитат:
Поправи ме ако греша, но ето какво се случва в този примерен код за dependency injection. Да кажем имаме клас, който се грижи за създаването на обектите. В случая аз инжектирам Connection в два различни класа и съответно ще бъдат създадени два обекта, което пък значи че ще имам две конекции.

Ти ще инжектираш само един Connection? Няма да правиш втори.
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
teroristd
Редовен
Редовен

Регистриран на: 18/02/2010 1:50 pm

Support: 80
Bonus: 172
Мнения: 1561
Мнение 25/05/2017 3:03 pm      Отговорете с цитат


anonimen написа:
Цитат:
Поправи ме ако греша, но ето какво се случва в този примерен код за dependency injection. Да кажем имаме клас, който се грижи за създаването на обектите. В случая аз инжектирам Connection в два различни класа и съответно ще бъдат създадени два обекта, което пък значи че ще имам две конекции.

Ти ще инжектираш само един Connection? Няма да правиш втори.


Това не го разбрах. Какво значи няма да правиш втори? Те обектите се създават автоматично.
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
anonimen
Активен
Активен

Регистриран на: 11/06/2012 8:07 pm

Support: 141
Bonus: 281
Мнения: 1307
Мнение 25/05/2017 3:06 pm      Отговорете с цитат


Цитат:
В случая аз инжектирам Connection в два различни класа и съответно ще бъдат създадени два обекта, което пък значи че ще имам две конекции.


PHP code:
$connection = /* по някакъв начин получаваш конекцията.
Може с new, или от някъде другаде */;

$modelOne = new ModelOne($connection);
$modelTwo = new ModelTwo($connection);


Така имаш една инстанция на конекцията в 2 обекта.
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
teroristd
Редовен
Редовен

Регистриран на: 18/02/2010 1:50 pm

Support: 80
Bonus: 172
Мнения: 1561
Мнение 26/05/2017 10:43 am      Отговорете с цитат


anonimen написа:
Цитат:
В случая аз инжектирам Connection в два различни класа и съответно ще бъдат създадени два обекта, което пък значи че ще имам две конекции.


PHP code:
$connection = /* по някакъв начин получаваш конекцията.
Може с new, или от някъде другаде */;

$modelOne = new ModelOne($connection);
$modelTwo = new ModelTwo($connection);


Така имаш една инстанция на конекцията в 2 обекта.


Принципно е така, обаче този пример е прекалено прост и при мене реално няма как да се случи. Ето как стоят нещата при мен.

Входа ми е един index.php в който, зареждам в този ред Config, Loader и Container.

Config ми е много важен защото с него зареждам различни масиви с конфигурации и го ползвам на много места в приложението, и той е един от класовете който, искам да има само една инстанция.

За Loader е ясно само ще добавя че и той ползва Config.

В Container вече чрез reflection правя обектите. Имам един метод make, който получава като параметър име на клас. Правя проверки дали в конструктора е инжектиран интерфейс, нормален клас, сингълтон и т.н. и зареждам според проверките правилния клас, който вече също може да си има зависимости и така. Класът който подавам като параметър на Container е App. В него инжектирам всички останали класове, които ми трябват, като Validator, View, FrontController и т.н. Това всичко е преди да съм почнал да пиша някакъв сайт примерно.
Основното е че след Container всичко се инжектира, и няма къде да пиша да го наречем свободен код Smile като примера който си дал горе. Реално единственото място в което имам new class() e index.php.

PHP code:

require_once realpath('../application/Config.php');
require_once realpath('../application/Loader.php');
$loader = application\Loader::getInstance();
$loader->load();
$container = application\Container::getInstance();
$app = $container->make('application\App');
$app->appRun();


Ще дам и бейсик пример с контролер и един модел, все едно почвам да пиша някакъв сайт.

PHP code:

Class UserController {
private $_view;
private $_model;
public function __construct(View $view, UserModel $model) {
$this->_view = $view;
$this->_model = $model;
}
public function register() {
$this->_model->register($firstName);
$this->_view->display('register');
}
}

Class UserModel {
private $_database;
private $_validation;
public function __construct(Database $database, Validation $validation){
$this->_database = $database;
$this->_validation = $validation;
}
public function register($firstName) {
$this->_validation->setRule('alphacyrillic', $firstName, '', 'alpha');
if ($this->_validation->validate() === TRUE) {
$this->_database->prepare('INSERT INTO user (first_name) VALUES(?)', array ($firstName))->execute(); }
}
}


Както виждаш всички обекти идват в конструкторите. Нека си представим че имам други модели и контролери, които не са свързани по никакъв начин с тези, но трябва да ползват същата инстанция на database, на Config, и на т.н. В случая тези класове са ми сингълтони и всичко си е ок, ама нали е антипатерн Smile . За това питам за алтернатива.

Доста дълъг ми стана поста, дано да ме разберете Smile .
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
anonimen
Активен
Активен

Регистриран на: 11/06/2012 8:07 pm

Support: 141
Bonus: 281
Мнения: 1307
Мнение 26/05/2017 3:48 pm      Отговорете с цитат


Просто в контейнера гледаш дали няма вече създадена ДБ връзка? Ако има - даваш нея. Ако няма - правиш нова.
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
teroristd
Редовен
Редовен

Регистриран на: 18/02/2010 1:50 pm

Support: 80
Bonus: 172
Мнения: 1561
Мнение 26/05/2017 4:58 pm      Отговорете с цитат


Извинявай колега, може аз да не те разбирам, или ти не четеш какво съм написал.
Не се хващай за примера с конекцията. Има и още класове които трябва да са сингълтони. А може и по време на писане да изникнат още. Аз контейнера няма как да седна да го преправям всеки път.
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
anonimen
Активен
Активен

Регистриран на: 11/06/2012 8:07 pm

Support: 141
Bonus: 281
Мнения: 1307
Мнение 26/05/2017 10:12 pm      Отговорете с цитат


teroristd написа:
Извинявай колега, може аз да не те разбирам, или ти не четеш какво съм написал.
Не се хващай за примера с конекцията. Има и още класове които трябва да са сингълтони. А може и по време на писане да изникнат още. Аз контейнера няма как да седна да го преправям всеки път.

Защо тогава не укажеш изрично на контейнера кои класове трябва да се зареждат еднократно и кои - всеки път?

PHP code:
class Container {
$instantiationRules = [];
$cached = [];

// после, при създаването на инстанцията:
switch ($instantiationRules[$class]) {
case SINGLETON: $instance = new $class; break;
case KEEP_INSTANCE:
if(!$cached[$class]) $cached[$class] = new $class;
$instance = $cached[$class];
break;
default:
$instance = new $class;
}

}

// При създаването на контейнера:

$container->addRule(Database::class, Container::KEEP_INSTANCE);
$container->addRule(UserController::class, Container::SINGLETON);
// и т.н.
// a може и директно в $instantiationRules да пипаш. Както ти е удобно.
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
teroristd
Редовен
Редовен

Регистриран на: 18/02/2010 1:50 pm

Support: 80
Bonus: 172
Мнения: 1561
Мнение 27/05/2017 8:37 am      Отговорете с цитат


Така може и да се получи. Изникна ми един въпрос обаче. Как мога да тествам(да проверя) дали даден клас е една и съща инстанция?
Върнете се в началото
Вижте профила на потребителя Изпратете лично съобщение
Покажи мнения от преди:    
Създайте нова тема   Напишете отговор    web-tourist.net Форуми -> Дъра-бъра Часовете са според зоната GMT + 2 Часа
12345
Страница 1 от 5


 
Идете на:  
Не Можете да пускате нови теми
Не Можете да отговаряте на темите
Не Можете да променяте съобщенията си
Не Можете да изтривате съобщенията си
Не Можете да гласувате в анкети