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

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

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

Если же пользователю класса нужны детали реализации, значит вы решаете задачи разного уровня абстракции в одном участке кода.
 
Инстанцирование - создание объекта. Так как в твоем примере неинициализированный объект = бесполезный объект, следовательно там где инстанцирование будет и код инициализации. Теперь представь, что рефакторинг 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:
$db = Db::getInstance();
$db->Open(....);
у меня синглетон работает - и проблем не возникало ни когда.
 
triumvirat да, правильно. Я даже не придирусь ;) к тому, что ты инстанцируешь экземпляр Database в конструкторе фабрики, вместо того, что бы сделать по аналогии с юзером. Ведь это легко поправить и на работе с User никак не скажется.
 
$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();
    }
 
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;
 
зы:
не всегда согласен с завышением роли агрегации в сравнении с наследованием
очень часто "глобальные" сигнатуры с ссылками на базовый класс/интерфейс + локальные конкретные имена упрощают понимание кода + существенно уменьшают время отладки

-~{}~ 27.03.08 23:04:

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

ну так правильно или нет? :)
 
В общем, разговор свелся к тому, что в моих примерах нужно в фабрике инстанцировать экземпляр 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;
        }
    }
}
 
Сверху