как передать объект класса в другой класс?

whirlwind

TDD infected, paranoid
Ведь все равно придется в самой фабрике завязывать user на $dbObject-e, т.е. как-то придется передавать в класс user объект БД.
Да, но фабрика одна, а пользователей класса user может быть мильен. Что ты выберешь, менять код одной фабрики которая делает четко обозначенную узкоспециализированную задачу, или менять милион точек инстанцирования класса User, которые занимаются самыми разными вещами?

Фабрика скрывает то, что пользователю класса абсолютно не нужно знать для работы. Например для пользователя класса User абсолютно должно быть по барабану хранятся ли данные пользователя в БД, или получаются через SOAP с другого сервера или еще как то.

Если же пользователю класса нужны детали реализации, значит вы решаете задачи разного уровня абстракции в одном участке кода.
 

whirlwind

TDD infected, paranoid
Инстанцирование - создание объекта. Так как в твоем примере неинициализированный объект = бесполезный объект, следовательно там где инстанцирование будет и код инициализации. Теперь представь, что рефакторинг User требует новых шагов инициализации (например, ты внедрил механизм событий и нужно подписать каждый экземпляр User). Для того, что бы это сделать, тебе потребуется найти в проекте и изменить все места, где у тебя создается экземпляр User. Использование фабрики избавляет от этих ненужных телодвижений.
 

Духовность™

Продвинутый новичок
Так чтоли это должно выглядеть?
PHP:
class Database
{
	public function __construct()
	{
		$this->foo = 'я свойство объекта класса Database';
	}
}

class user
{
	public function __construct($db)
	{
		$this->db = $db;
	}
	
	public function execute()
	{
		echo $this->db->foo;
	}
}

class factory
{
	public function __construct()
	{
		$this->db = new Database();
	}
	
	public function createUser()
	{
		return new user($this->db);
	}
}

$fact = new factory();

$user = $fact->createUser();

// работаем с user 
$user->execute();
 

Alexandre

PHPПенсионер
Alexandre, это не будет работать.
соглаен.... поспешишь - людей насмешишь...
код подправил на
PHP:
$db = Db::getInstance();
$db->Open(....);
у меня синглетон работает - и проблем не возникало ни когда.
 

whirlwind

TDD infected, paranoid
triumvirat да, правильно. Я даже не придирусь ;) к тому, что ты инстанцируешь экземпляр Database в конструкторе фабрики, вместо того, что бы сделать по аналогии с юзером. Ведь это легко поправить и на работе с User никак не скажется.
 

Духовность™

Продвинутый новичок
вместо того, что бы сделать по аналогии с юзером
в смысле? ты хочешь сказать, что лучше в фабрику передавать объект Database? Типо
PHP:
$db = SingletonClass::getInstance(); ; 
$fact = new factory($db);
так чтоли? :)
 

Alexandre

PHPПенсионер
$db = SingletonClass::getInstance(); ;
$fact = new factory($db);
если так, то так глупо, ибо зачем тогда нужен синглетон,
если его можно вызвать в любом месте:
class someClass {
function foo(){
$db = SingletonClass::getInstance();
}
}

$fact = new someClass()

-~{}~ 27.03.08 20:50:

class user
{
public function __construct($db)
{
$this->db = $db;
}

public function execute()
{
echo $this->db->foo;
}
}
делай так:
PHP:
  public function execute()
    {
        $db = DB::GetInstance()
        $db->execute();
    }
 

StUV

Rotaredom
whirlwind
хм
если в разных местах кода - разные "юзеры"... - инстанциирующие методы фабрики получают "по месту" в принципе неограниченное число параметров и включают "в одно место" все немыслимые варианты обработки этих параметров ?..
или я что-то "непонял"... ?
 

Духовность™

Продвинутый новичок
получение через фабрику эеземпляра для работы с БД.
так чтоли?

PHP:
class Database
{
    public function __construct()
    {
        $this->foo = 'я свойство объекта класса Database';
    }
}

class user
{
    public function __construct($db)
    {
        $this->db = $db;
    }
    
    public function execute()
    {
        echo $this->db->foo;
    }
}

class factory
{
    public function __construct(){}
	
    // возвращает объект "база данных"
	public function createDatabase()
	{
		if (null == $this->db)
		{
			$this->db = new Database();
		}
		
		return $this->db;
	}
	
	// возвращает объект "пользователь"
    public function createUser()
    {
		$this->createDatabase();
		
        return new user($this->db);
    }
}

$fact = new factory();

$user = $fact->createUser();

// работаем с user 
$user->execute();

// хотим иметь объект БД
$db = $fact->createDatabase();

// работаем с $db
echo '<br>'.$db->foo;
 

StUV

Rotaredom
зы:
не всегда согласен с завышением роли агрегации в сравнении с наследованием
очень часто "глобальные" сигнатуры с ссылками на базовый класс/интерфейс + локальные конкретные имена упрощают понимание кода + существенно уменьшают время отладки

-~{}~ 27.03.08 23:04:

triumvirat
что-то ты в паттернах совсем запутался...
 

Sluggard

Новичок
triumvirat
Ну как один из вариантов. :) Только при таком способе
PHP:
$fact = new factory();
и
PHP:
$this->db = new Database();
у тебя один экземпляр класса Database существует только в рамках этого экземпляра.
 

StUV

Rotaredom
Sluggard
Ну как один из вариантов
да это не вариант - это бред полный

triumvirat
оч рекомендую забыть про паттерны, почитать Буча, спроектировать и отрисовать в uml среднего уровня _модульное_ приложение (лучше не одно)
потом вернуться к паттернам/фаулеру/...

пойми - у тебя в голове каша из несвязных терминов
"шаблонное" понимание архитектуры ценно в _общении_между_опытными_ разработчиками/архитекторами, а не в бессмысленном "правильном" их использовании
 

Духовность™

Продвинутый новичок
StUV
аха, почитаю обязательно )

В общем, разговор свелся к тому, что в моих примерах нужно в фабрике инстанцировать экземпляр Database. Но поскольку объект Database должен быть один, то тут очевидно нужно использовать ещёт и singleton. Вот что у меня в конечном счете получилось:
PHP:
// Обычный Singleton.
// В Singleton-е инстанцирую объект класса Database - он должен быть в единичном экземпляре!
class Singleton
{
	private static $instanse;
	private static $db;
	
	function __construct(){}
	
	private function init()
	{
		self::$db = new Database();
	}
	
	function getInstanse()
	{
		if (self::$instanse === null)
		{
			self::$instanse = new self;
			self::init();
		}
		
		return self::$instanse;
	}
	
	function getDatabase()
	{
		return self::$db;
	}
}

// Фабрика, возвращает объект с помощью метода getObject(),
// параметром которого служит строка - имя инстанцируемого объекта.
class factory
{
    function __construct(){}
	
	function getObject($objName)
	{
		switch($objName)
		{
			case 'user':
				return new User( Singleton::getInstanse()->getDatabase() );
				break;
			// ....
			case 'database':
				return Singleton::getInstanse()->getDatabase();
				break;
		}
	}
}

// Класс Database. 
// Объект этого класса присутсвует лишь в единичном экземпляре!
class Database
{
    function __construct()
    {
        $this->foo = 'я свойство объекта класса Database';
    }
}

// Объектов класса User может быть сколь угодно много.
class User
{
    public function __construct($db)
    {
        $this->db = $db;
    }
    
    public function execute()
    {
        echo $this->db->foo.
		', я получено из класаа '.__CLASS__;
    }
}



$fact = new factory();

// Получаем объект user
$user = $fact->getObject('user');

// Работаем с user (используя объект Database)
$user->execute();

// Хотим иметь объект БД непосредственно в коде
$db = $fact->getObject('database');

// Работаем непосредственно с объектом Database
echo '<br>'.$db->foo.', получено прямо в коде программы';
Выводит:

я свойство объекта класса Database, я получено из класаа User
я свойство объекта класса Database, получено прямо в коде программы

-~{}~ 28.03.08 15:01:

ну так правильно или нет? :)
 

Alexandre

PHPПенсионер
В общем, разговор свелся к тому, что в моих примерах нужно в фабрике инстанцировать экземпляр Database. Но поскольку объект Database должен быть один, то тут очевидно нужно использовать ещёт и singleton. Вот что у меня в конечном счете получилось:
triumvirat У тебя точно каша в голове.

инстацируешь один экземпляр DB
инстацируешь один экземпляр User , передаешь ссылку на экземпляр DB в конструкторе класса User или методом $user->setDb($db);
а, метод setDb($db) сохранит ссылку в поле (private) $user->_db;

все! и не парься..... Чем порще, тем лучше.
 

Духовность™

Продвинутый новичок
Alexandre
Да я просты пытаюсь понять, правильно ли ТАК фабрику использовать или нет.

-~{}~ 28.03.08 16:24:

инстацируешь один экземпляр DB
инстацируешь один экземпляр User , передаешь ссылку на экземпляр DB в конструкторе класса User или методом
я так и сделал:
PHP:
class factory
{
    function __construct(){}
    
    function getObject($objName)
    {
        switch($objName)
        {
            case 'user':
                return new User( Singleton::getInstanse()->getDatabase() );
                break;
            // ....
            case 'database':
                return Singleton::getInstanse()->getDatabase();
                break;
        }
    }
}
 
Сверху