Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Factory pattern implementation using ANSI C

Can anyone point me to a reference on how to implement the factory pattern using ANSI C? If more patterns are covered to that would just be a bonus. Doing this in C++ i trivial for me, but since C does not have classes and polymorphism I'm not quite sure how to do it. I was thinking about having a "base" struct with all the common data types and then using void pointers, and defining all the common parts of the structs in the same order as in the base struct at the top? Or is it not guaranteed that they end up in the same way in memory?

like image 684
inquam Avatar asked Jan 21 '23 19:01

inquam


2 Answers

Factory pattern can be implemented in C also, suppose the following are the operations that your interface defines:

typedef int (*operations_1) (void *data);
typedef int (*operations_2) (void *data);

typedef struct impl_ops_t
{
    operations_1 op1;
    operations_2 op2;
} impl_ops_t;

So, to be able to get an implementations instance that implements such interface, you should define a structure with both data and operations, then you can define the create operation that will return to you that structure and probably a destroy operations also:

typedef struct ctx_t
{
    void       *data;
    impl_ops_t *operations;
} ctx_t;

typedef ctx_t   (*create_handle)   (void);
typedef void    (*destroy_handle)  (ctx_t **ptr);

typedef struct factory_ops
{
    create_handle  create;
    destroy_handle destroy;
} factory_ops;

You should also define a function that provides you the factory methods, maybe you should have a way to get the right implementation basing on your needs (probably not a simple parameter like in the example below):

typedef enum IMPL_TYPE
{
    IMPL_TYPE_1,
    IMPL_TYPE_2
} IMPL_TYPE;
factory_ops* get_factory(int impl_type);

So it will be used like:

main (...)
{
    factory_ops fact = get_factory(IMPL_TYPE_2);

    // First thing will be calling the factory method of the selected implementation
    // to get the context structure that carry both data ptr and functions pointer
    ctx_t *c = fact->create();

    // So now you can call the op1 function
    int a = c->operations->op1(c->data);
    // Doing something with returned value if you like..
    int b = c->operations->op2(c->data);
    // Doing something with returned value if you like..

    fact->destroy(&c);
    return 0;
}
like image 85
Giordano Avatar answered Jan 28 '23 15:01

Giordano


C have function pointers and structs. So you can implement classes in C.

something like this should give you a clue.

void class1_foo() {}
void class2_foo() {}

struct polyclass
{
    void (*foo)();
};

polyclass make_class1() { polyclass result; result.foo = class1_foo; return result; }
like image 26
yatagarasu Avatar answered Jan 28 '23 14:01

yatagarasu