Реализация на фабричен модел с помощта на ANSI C

Може ли някой да ме насочи към справка за това как да внедря фабричния модел с помощта на ANSI C? Ако са покрити повече модели, това би било просто бонус. Правенето на това в C++ е тривиално за мен, но тъй като C няма класове и полиморфизъм, не съм съвсем сигурен как да го направя. Мислех си да имам "базова" структура с всички общи типове данни и след това да използвам празни указатели и да дефинирам всички общи части на структурите в същия ред, както в основната структура в горната част? Или не е гарантирано, че ще се озоват по същия начин в паметта?


person inquam    schedule 08.07.2010    source източник
comment
Можете да направите полиморфизъм в C, но не е красиво. Вижте тези въпроси: stackoverflow.com/questions/524033/ stackoverflow.com/questions/351733/ stackoverflow.com/questions/415452/object-orientation-in-c   -  person Adam Rosenfield    schedule 08.07.2010


Отговори (4)


C има функционални указатели и структури. Така че можете да реализирате класове в C.

нещо подобно трябва да ви даде представа.

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

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

polyclass make_class1() { polyclass result; result.foo = class1_foo; return result; }
person yatagarasu    schedule 08.07.2010

Фабричният модел може да бъде имплементиран и в C, да предположим, че следните са операциите, които вашият интерфейс дефинира:

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;

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

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;

Трябва също да дефинирате функция, която ви предоставя фабричните методи, може би трябва да имате начин да получите правилната реализация въз основа на вашите нужди (вероятно не е прост параметър като в примера по-долу):

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

Така че ще се използва като:

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;
}
person Giordano    schedule 26.03.2013
comment
Поздравления! Това е хубав и чист пример! Благодаря! - person kazbeel; 08.09.2014
comment
Нов съм във фабричния шаблон и пиша само C. Този пример ми е много контраинтуитивен. Защо просто не се обадите директно на operations_1 и operations_2? Има ли полза от използването на указател към указател за функция? - person Andy Lin; 10.01.2021
comment
За да разберете причините, бих ви препоръчал да опитате да приложите такъв фабричен модел, без да използвате указател на функция - person Giordano; 18.01.2021

Тук, в долната част на страницата, има поредица от статии за модели в C

person pcent    schedule 08.07.2010

Фабричният шаблон е обектно-ориентиран шаблон за проектиране.

C не е обектно-ориентиран език.

Затова бих се запитал каква е вашата цел за фабрика в C.

person Justin Niessner    schedule 08.07.2010
comment
Че модулът, който ще създам, е наистина подходящ за фабричния дизайн. Но компанията има строга политика да използва само ansi C. - person inquam; 08.07.2010
comment
@inquam – Разбираемо, но бихте ли могли да ни дадете пример за какво искате фабриката (тъй като обикновено фабриката се използва за създаване на екземпляр на интерфейс, подкрепен от различни реализации на клас)? - person Justin Niessner; 08.07.2010
comment
Знам и това е, което искам... Но трябва да се боря с ограниченията на C. Да речем, че изградите система, която ще сканира за вируси във файловете и ще докладва констатациите. Има много различни начини и в бъдеще може да се появят повече за откриване на различните вируси. Но частта за отчитане за всички тях е една и съща. Ако можех да имам начин да направя базата със структура от данни за съхраняване на отчетни данни и т.н. по подобен начин, всички различни скенери биха могли да изпълняват едни и същи отчетни функции. Но действителната работа, която трябва да сканират, може да е различна. - person inquam; 08.07.2010
comment
Не съм съгласен. Обектната ориентация е парадигма, парадигма, която може да се реализира с помощта на C. Не казвам обаче, че това е добра идея. - person manneorama; 08.07.2010
comment
@manneorama - Обектно ориентираното програмиране се определя като език, поддържащ три основни концепции: наследяване, полиморфизъм и капсулиране. Без наследяване и полиморфизъм...C не отговаря на изискванията. - person Justin Niessner; 08.07.2010
comment
@Justin, Всичко, което е възможно да се постигне с помощта на C. Разгледайте този въпрос например; stackoverflow.com/questions/415452/object-orientation- in-c/. Сега, аз не твърдя, че C е проектиран да бъде използван по обектно-ориентиран начин и не казвам, че трябва да се използва по такъв начин, вместо може би по-способен език. Казвам, че ако някой по някаква причина иска да го направи, това е възможно и може да се направи. Със значителни усилия и много малка печалба =) - person manneorama; 08.07.2010