construção de objetos

26 views
Skip to first unread message

Canellas

unread,
Apr 16, 2013, 9:16:47 AM4/16/13
to ccppbrasil
Caros,

Gostaria de saber suas opiniões sobre duas abordagens de construção de objetos, exemplificadas no código abaixo.

Antecipadamente agradeço.

#include <iostream>
#include <cstdint>

class a_factory;

class a {
  friend class a_factory;
public:

  a( const a & p_a )
  : m_id ( p_a.m_id ) {}
  
  void m( ) {
    std::cout << "I am a 'a' object # " << m_id << std::endl;
  }

  a & operator = ( const a & p_a ) {
    if ( this != & p_a ) {
      m_id = p_a.m_id;
    }
    return *this;
  }

private:
  a( uint16_t p_id )
    : m_id( p_id ) {}

  uint16_t m_id;
};


class a_factory {
public:

  a_factory( )
    : m_counter( 0 ) {}

  a create( ) {
    return a( m_counter++ );
  }

private:
  uint16_t m_counter;
};


class b {

public:

  static b create( ) {
    return b( m_counter++ );
  }

  b( const b & p_b )
  : m_id ( p_b.m_id ) {}
  
  void m( ) {
    std::cout << "I am a 'b' object # " << m_id << std::endl;
  }

  b & operator = ( const b & p_b ) {
    if ( this != & p_b ) {
      m_id = p_b.m_id;
    }
    return *this;
  }

private:
  b( uint16_t p_id )
    : m_id( p_id ) {}

  uint16_t m_id;

  static uint16_t m_counter;
};

uint16_t b::m_counter( 0 );
  
int main( ) {

  a_factory l_a_factory;

  a l_a1 = l_a_factory.create( );
  a l_a2 = l_a_factory.create( );

  l_a1.m( );
  l_a2.m( );


  // =================

  b l_b1 = b::create( );
  b l_b2 = b::create( );  

  l_b1.m( );
  l_b2.m( );

}


    Rodrigo Canellas

    -----------
    Programador C++
    Fotógrafo amador
 


Rodrigo Madera

unread,
Apr 16, 2013, 11:03:16 AM4/16/13
to ccppb...@googlegroups.com
l_Rapaz l_eu _p_ate _t_tentei _ler_ m_mas _l_ficou _e_estranho m_de _l_p_ler.

=(


2013/4/16 Canellas <rodrigo....@gmail.com>

--
Antes de enviar um e-mail para o grupo leia:
http://www.ccppbrasil.org/wiki/Lista:AntesdePerguntar
--~--~---------~--~----~---------------------------------~----------~--~----~
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
Para mais opções, visite http://groups.google.com/group/ccppbrasil
--~--~---------~--~----~--~-~--~---~----~-----------------~--~----------~
Emprego & carreira: vag...@ccppbrasil.org
http://groups.google.com/group/dev-guys?hl=en
 
 
 

Rodrigo Avancini

unread,
Apr 16, 2013, 11:14:49 AM4/16/13
to ccppb...@googlegroups.com
Jovem,

Qual é a duvida?

Att.
Rodrigo

Canellas

unread,
Apr 16, 2013, 12:10:43 PM4/16/13
to ccppbrasil
Obrigado pelo 'jovem'! 8)

Não há dúvida, só gostaria de saber opiniões, como "Acho os 2 ruins", "O primeiro se aplica melhor nessa situação, o outro naquela", "Este tem essas vantagens/desvantagens", etc etc...

    Rodrigo Canellas

    -----------
    Programador C++
    Fotógrafo amador
 




2013/4/16 Rodrigo Avancini <avancin...@gmail.com>

Rodrigo Madera

unread,
Apr 16, 2013, 12:12:31 PM4/16/13
to ccppb...@googlegroups.com
Canellas,

As vezes seria melhor expor os conceitos com texto, dai fica mais fácil opinar.

Me parece que você está perguntando de factory vs factory method? Posso estar enganado, apenas vi por cima.

Vejo que reimplementou contagem de referências de algum tipo. Shared_ptr ou similares consagrados e testados não resolvem?

Mx


2013/4/16 Canellas <rodrigo....@gmail.com>

Canellas

unread,
Apr 16, 2013, 12:17:33 PM4/16/13
to ccppbrasil
Rodrigo,

Não estou preocupado com a maneira do factory controlar os objetos criados, mas comparar a estratégia de criação de objetos por uma classe "externa" à classe a ser instanciada; contra a da classe a ser instanciada ter um método estático. 

Desculpe se a forma de apresentar o problema não foi boa, mas achei que um código (o mais) simples (que consegui escrever) facilitaria entender a questão.

Rodrigo Madera

unread,
Apr 16, 2013, 12:20:39 PM4/16/13
to ccppb...@googlegroups.com
2013/4/16 Canellas <rodrigo....@gmail.com>

Não estou preocupado com a maneira do factory controlar os objetos criados, mas comparar a estratégia de criação de objetos por uma classe "externa" à classe a ser instanciada; contra a da classe a ser instanciada ter um método estático. 

Faz tempo que não leio GoF, mas não é essa a diferença entre os padrões factory e factory method?

Particularmente eu voto em deixar a classe o mais simples possível, e no caso, deixo a criação delegada em free functions que criam quando preciso, a la make_xpto(), por exemplo. Ah, e evito ao máximo declarar friends.

Mx

Thiago Adams

unread,
Apr 16, 2013, 12:22:50 PM4/16/13
to ccppb...@googlegroups.com

2013/4/16 Canellas <rodrigo....@gmail.com>

Obrigado pelo 'jovem'! 8)

Não há dúvida, só gostaria de saber opiniões, como "Acho os 2 ruins", "O primeiro se aplica melhor nessa situação, o outro naquela", "Este tem essas vantagens/desvantagens", etc etc...


Qual é a situação que você precisa disso? Qual é o objetivo?


 

Canellas

unread,
Apr 16, 2013, 12:23:15 PM4/16/13
to ccppbrasil
Consegui me fazer entender! Viva! hehehe

Obrigado por expor sua opinião!


abs

    Rodrigo Canellas

    -----------
    Programador C++
    Fotógrafo amador
 




--

Canellas

unread,
Apr 16, 2013, 12:25:22 PM4/16/13
to ccppbrasil
Esse é o objetivo da pergunta: em que situações você usaria qual deles? Ou mesmo se usaria qq um dos dois.

    Rodrigo Canellas

    -----------
    Programador C++
    Fotógrafo amador
 




--

Canellas

unread,
Apr 16, 2013, 12:29:38 PM4/16/13
to ccppbrasil
Rodrigo,

As free functions obrigariam que os construtores da classe (a ser instanciada) sejam públicos, certo? Sendo assim, não existe qq restrição à criação, i.e., qq código poderá instanciar, certo? Logo, free functions não me parece muito indicado se a criação deve ser "controlada" (por qq motivo), certo? 

abs

    Rodrigo Canellas

    -----------
    Programador C++
    Fotógrafo amador
 




Em 16 de abril de 2013 13:20, Rodrigo Madera <rodrigo...@gmail.com> escreveu:

--

Rodrigo Madera

unread,
Apr 16, 2013, 12:40:15 PM4/16/13
to ccppb...@googlegroups.com
2013/4/16 Canellas <rodrigo....@gmail.com>

restrição à criação, i.e., qq código poderá instanciar, certo? Logo, free functions não me parece muito indicado se a criação deve ser "controlada" (por qq motivo), certo? 

Nesse caso, parece que sim... mas raramente tenho esse problema. E quando tenho, me lembro de ter usado inner classes pra resolver. Não que eu diga que seja melhor, mas foi o que fiz na época. As vezes teu problema exige que seja assim.

Cada caso é um caso, e sem saber mais detalhes, acho que dizer uma ou outra é muita ingenuidade.

Boa sorte,
Mx

Canellas

unread,
Apr 16, 2013, 12:47:06 PM4/16/13
to ccppbrasil
Rodrigo,

De novo, obrigado. Porém, não concordo muito em ser ingenuidade. Acho perfeitamente possível discutir sobre estratégias com base em requisitos, sem um caso concreto. Verdade que não defini os requisitos, apresentando a questão "ao contrário": dados dois esboços de implementações, para quais requisitos elas serviriam? Bom, parece que não teve muito eco. 8)


abs,

    Rodrigo Canellas

    -----------
    Programador C++
    Fotógrafo amador
 




--

Gianni .

unread,
Apr 16, 2013, 12:53:42 PM4/16/13
to ccppb...@googlegroups.com

Eu geralmente uso factory methods. Fica mais simples e conciso.

 

Mas, se a maneira de construir os objetos for mais complexa, e depender de membros específicos (contadores, recursos, memory-pools, etc); aí acho melhor usar fectory class mesmo e não deixar tudo misturado num lugar só.

Уθя¡ςκ

unread,
Apr 16, 2013, 12:56:13 PM4/16/13
to ccppb...@googlegroups.com
On Tuesday, April 16, 2013 1:29:38 PM UTC-3, Rodrigo.Canellas wrote:
Rodrigo,

As free functions obrigariam que os construtores da classe (a ser instanciada) sejam públicos, certo? Sendo assim, não existe qq restrição à criação, i.e., qq código poderá instanciar, certo? Logo, free functions não me parece muito indicado se a criação deve ser "controlada" (por qq motivo), certo? 

Nota, funções friend existem.

Canellas

unread,
Apr 16, 2013, 1:21:38 PM4/16/13
to ccppbrasil
Entendo q uma friend function tenha acesso a membros privativos da classe, satisfazendo restrições de criação, certo? 

    Rodrigo Canellas

    -----------
    Programador C++
    Fotógrafo amador
 




--

Уθя¡ςκ

unread,
Apr 16, 2013, 1:23:51 PM4/16/13
to ccppb...@googlegroups.com
On Tuesday, April 16, 2013 2:21:38 PM UTC-3, Rodrigo.Canellas wrote:
Entendo q uma friend function tenha acesso a membros privativos da classe, satisfazendo restrições de criação, certo? 

yup 

Bruno Sanches

unread,
Apr 16, 2013, 1:25:59 PM4/16/13
to ccppb...@googlegroups.com
Se você precisa também por algum motivo restringir a criação de objetos e querer obrigar que a criação seja apenas pela factory, pode deixar os construtores como privados ou protected, deixando a factory como friend, assim o "usuário" só vai poder criar os objetos com a factory.

T+

Bruno Sanches
========================
http://www.pontov.com.br


2013/4/16 Уθя¡ςκ <obl...@gmail.com>
On Tuesday, April 16, 2013 2:21:38 PM UTC-3, Rodrigo.Canellas wrote:
Entendo q uma friend function tenha acesso a membros privativos da classe, satisfazendo restrições de criação, certo? 

yup 

--

Canellas

unread,
Apr 16, 2013, 1:28:10 PM4/16/13
to ccppbrasil
Esta é a situação das classes 'a' e 'a_factory' no código q enviei, certo?

    Rodrigo Canellas

    -----------
    Programador C++
    Fotógrafo amador
 




2013/4/16 Bruno Sanches <bcsa...@gmail.com>

Bruno Sanches

unread,
Apr 16, 2013, 1:30:34 PM4/16/13
to ccppb...@googlegroups.com
Isso!

Bruno Sanches
========================
http://www.pontov.com.br


Canellas

unread,
Apr 16, 2013, 1:43:35 PM4/16/13
to ccppbrasil
E o que acham disso:



#include <iostream>
#include <cstdint>

template <typename t_class>
class factory;


class c {
  friend class factory<c>;
public:

  c( const c & p_c )
  : m_id ( p_c.m_id ) {}
  
  void m( ) {
    std::cout << "I am a 'c' object # " << m_id << std::endl;
  }
  
  c & operator = ( const c & p_c ) {
    if ( this != & p_c ) {
      m_id = p_c.m_id;
    }
    return *this;
  }

private:
  c( uint16_t p_id )
    : m_id( p_id ) {}

  uint16_t m_id;
};


template <>
class factory<c> {
public:

  factory<c>( )
  : m_counter( 0 ) {}

  c create( ) {
    return c( m_counter++ );
  }

private:
  uint16_t m_counter;
};


int main( ) {

  factory<c> l_c_factory;

  c l_c1 = l_c_factory.create( );
  c l_c2 = l_c_factory.create( );

  l_c1.m( );
  l_c2.m( );
}

Rodrigo Madera

unread,
Apr 16, 2013, 1:53:22 PM4/16/13
to ccppb...@googlegroups.com
Qual... tua... intenção?


2013/4/16 Canellas <rodrigo....@gmail.com>

Canellas

unread,
Apr 16, 2013, 1:55:55 PM4/16/13
to ccppbrasil
Primeiramente... conversar... sobre... maneiras... de... criar... objetos. 8)

Essa última me parece bem interessante, pois permite criar diferentes estratégias de criação (de objetos de) uma mesma classe.


Thiago Adams

unread,
Apr 16, 2013, 3:06:40 PM4/16/13
to ccppbrasil


On Apr 16, 1:47 pm, Canellas <rodrigo.canel...@gmail.com> wrote:
> Rodrigo,
>
> De novo, obrigado. Porém, não concordo muito em ser ingenuidade. Acho
> perfeitamente possível discutir sobre estratégias com base em requisitos,
> sem um caso concreto. Verdade que não defini os requisitos, apresentando a
> questão "ao contrário": dados dois esboços de implementações, para quais
> requisitos elas serviriam? Bom, parece que não teve muito eco. 8)

O problema é que se você não colocar o caso específico a questão é
muito ampla.


P.

unread,
Apr 17, 2013, 11:14:27 AM4/17/13
to ccppb...@googlegroups.com
Em terça-feira, 16 de abril de 2013 13h17min33s UTC-3, Rodrigo.Canellas escreveu:
 
Não estou preocupado com a maneira do factory controlar os objetos criados, mas comparar a estratégia de criação de objetos por uma classe "externa" à classe a ser instanciada; contra a da classe a ser instanciada ter um método estático. 


A diferença nesse exemplo não está aparente porque não ocorre aí um cliente mais complexo dos "factory".

O objetivo geral de um "abstract factory" é configurabilidade.
Um caso concreto com o qual estou trabalhando agora é a interface especificada no PKCS #11.
Ao inicializar um módulo PKCS #11 o usuário tem a opção de informar a referência a um objeto que, entre outras atribuições, é uma fábrica de mutex.
Se o usuário informa uma referência válida, o módulo deve usar esta fábrica para criar e destruir mutex.
Se o usuário não informa nada, o módulo usa uma outra fábrica padrão.
As funções do módulo não precisam, posteriormente, tomar qualquer decisão com relação a isso -- apenas usam a fábrica configurada, qualquer ela seja.

Isso não é impossível de obter com uma função estática.
Se o objeto a ser configurado mantém um std::function de fabricação de objetos, então isto pode ser configurado como uma referência ao tal método.
Apesar da forma, isso ainda caracteriza uma "abstract factory", com o std::function faz o papel de interface e o método estático fazendo o papel de implementação.

Antes de std::function e similares, seria muito difícil obter este efeito usando métodos estáticos e funções livres, de modo que a única opção viável para sistemas em C++ seria usar classes abstratas e herança, como no exemplo do GoF.

Fora de relações de configurabilidade ou similares, as fábricas não trazem valor adicional aos construidores e operadores new.

--
 P.
Reply all
Reply to author
Forward
0 new messages