├── README.md ├── LICENSE ├── Makefile ├── singleton.c ├── decorator.c ├── prototype.c ├── factory-method.c ├── template-method.c ├── chain-of-responsibility.c ├── bridge.c ├── proxy.c ├── abstract-factory.c ├── adapter.c ├── facade.c ├── mediator.c ├── flyweight.c ├── observer.c ├── command.c ├── state.c ├── strategy.c ├── memento.c ├── iterator.c ├── visitor.c ├── interpreter.c └── composite.c /README.md: -------------------------------------------------------------------------------- 1 | # Design Patterns 2 | 3 | Included in this repository are simple C implementations of the design patterns 4 | described in [Design Patterns](https://en.wikipedia.org/wiki/Design_Patterns) 5 | by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (collectively 6 | known as the Gang of Four). 7 | 8 | This is more of a personal challenge to work through all the design 9 | patterns over time and have an example implementation for reference. 10 | 11 | 12 | # Why C? 13 | 14 | C is a rudimentary programming language that doesn't have any out-of-the-box 15 | support for the design patterns. Most higher level languages such as Java or 16 | Python have built-in support for some of the structural patterns such as 17 | iterators or decorators. 18 | 19 | Granted, the patterns in the book are geared towards object-oriented programming 20 | languages such as C++, and C is not technically a OOP language. However, this 21 | adds to the challenge of implementation and deepens my study of them. 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Jan Markowski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -ggdb -std=c11 2 | 3 | DP_CREATIONAL = 4 | DP_STRUCTURAL = 5 | DP_BEHAVIORAL = 6 | 7 | # Creational design patterns 8 | DP_CREATIONAL += abstract-factory 9 | DP_CREATIONAL += builder 10 | DP_CREATIONAL += factory-method 11 | DP_CREATIONAL += prototype 12 | DP_CREATIONAL += singleton 13 | 14 | # Structural design patterns 15 | DP_STRUCTURAL += adapter 16 | DP_STRUCTURAL += bridge 17 | DP_STRUCTURAL += composite 18 | DP_STRUCTURAL += decorator 19 | DP_STRUCTURAL += facade 20 | DP_STRUCTURAL += flyweight 21 | DP_STRUCTURAL += proxy 22 | 23 | # Behavioral design patterns 24 | DP_BEHAVIORAL += chain-of-responsibility 25 | DP_BEHAVIORAL += command 26 | DP_BEHAVIORAL += interpreter 27 | DP_BEHAVIORAL += iterator 28 | DP_BEHAVIORAL += mediator 29 | DP_BEHAVIORAL += memento 30 | DP_BEHAVIORAL += observer 31 | DP_BEHAVIORAL += state 32 | DP_BEHAVIORAL += strategy 33 | DP_BEHAVIORAL += template-method 34 | DP_BEHAVIORAL += visitor 35 | 36 | DP_ALL = $(DP_CREATIONAL) $(DP_STRUCTURAL) $(DP_BEHAVIORAL) 37 | 38 | all: $(DP_ALL) 39 | 40 | creational: $(DP_CREATIONAL) 41 | 42 | structural: $(DP_STRUCTURAL) 43 | 44 | behavioral: $(DP_BEHAVIORAL) 45 | 46 | %: 47 | gcc $(CFLAGS) -o $@ $(addsuffix .c,$@) 48 | 49 | clean: 50 | rm -rf $(DP_ALL) 51 | 52 | .PHONY: all creational structural behavioral clean 53 | -------------------------------------------------------------------------------- /singleton.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Ensure a class only has one instance, and provide a global point of access 7 | * to it. 8 | */ 9 | 10 | /** 11 | * Use the Singleton pattern when 12 | * - there must be exactly one instance of a class, and it must be accessible 13 | * to clients from a well-known access point. 14 | * - when the sole instance should be extensible by subclassing, and clients 15 | * should be able to use an extended instance without modifying their code. 16 | */ 17 | 18 | /** 19 | * - defines an Instance operation that lets clients access its unique instance. 20 | * - may be responsible for creating its own unique instance. 21 | */ 22 | typedef struct Singleton_s { 23 | int id; 24 | 25 | int (*getInstance)(struct Singleton_s *self); 26 | void (*operation)(struct Singleton_s *self); 27 | } Singleton_t; 28 | 29 | static void singletonOperation(Singleton_t *this) 30 | { 31 | printf("Singleton %d: operation\n", this->getInstance(this)); 32 | } 33 | 34 | static int singletonGetInstance(Singleton_t *this) { 35 | return this->id; 36 | } 37 | 38 | /* Private class constructor, should never be callable */ 39 | static Singleton_t * newSingleton(void) 40 | { 41 | static int id; 42 | 43 | Singleton_t *singleton = (Singleton_t *) malloc(sizeof(Singleton_t)); 44 | 45 | singleton->getInstance = singletonGetInstance; 46 | singleton->operation = singletonOperation; 47 | singleton->id = id++; 48 | 49 | return singleton; 50 | } 51 | 52 | /* Static class method, hence, global */ 53 | Singleton_t * singletonInstance(void) 54 | { 55 | static Singleton_t *instance; 56 | 57 | if (instance == 0) { 58 | instance = newSingleton(); 59 | } 60 | 61 | return instance; 62 | } 63 | 64 | int main(void) 65 | { 66 | Singleton_t *firstInstance = singletonInstance(); 67 | 68 | firstInstance->operation(firstInstance); 69 | 70 | Singleton_t *secondInstance = singletonInstance(); 71 | 72 | secondInstance->operation(secondInstance); 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /decorator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Attach additional responsibilities to an object dynamically. Decorators 7 | * provide a flexible alternative to subclassing for extending functionality. 8 | */ 9 | 10 | /** 11 | * Use the Decorator 12 | * - to add responsibilities to individual objects dynamically and 13 | * transparently, that is, without affecting other objects 14 | * - for responsibilities taht can be withdrawn. 15 | * - when extension by subclassing is impractical. Sometimes a large number of 16 | * independent extensions are possible and owuld produce an explosion of 17 | * subclasses to support every combination. Or a class definition may be hidden 18 | * or otherwise unavailable for subclassing. 19 | * 20 | * The Decorator pattern may also be referred to as a Wrapper. 21 | */ 22 | 23 | typedef struct Component_s { 24 | void (*operation)(const char * const str); 25 | } Component_t; 26 | 27 | static void componentOperation(const char * const str) 28 | { 29 | printf("%s: operation\n", str); 30 | } 31 | 32 | Component_t * newComponent(void) 33 | { 34 | Component_t *component = (Component_t *) malloc(sizeof(Component_t)); 35 | 36 | component->operation = componentOperation; 37 | 38 | return component; 39 | } 40 | 41 | static void decoratorAddedOperation(const char * const str) 42 | { 43 | printf("%s: added operation\n", str); 44 | } 45 | 46 | typedef struct Decorator_s { 47 | /* Methods inherited from Component_t */ 48 | void (*operation)(const char * const str); 49 | 50 | /* New attributes/methods */ 51 | void (*addedOperation)(const char * const str); 52 | } Decorator_t; 53 | 54 | Decorator_t * newDecorator(Component_t *component) 55 | { 56 | Decorator_t *decorator = (Decorator_t *) malloc(sizeof(Decorator_t)); 57 | 58 | decorator->operation = component->operation; 59 | decorator->addedOperation = decoratorAddedOperation; 60 | } 61 | 62 | int main(void) 63 | { 64 | Component_t *component = newComponent(); 65 | 66 | component->operation("Component"); 67 | 68 | /* 69 | * The power in the decorator is here, where you can take an existing 70 | * component and then "decorate" it with some added functionality. 71 | */ 72 | Decorator_t *decoratedComponent = newDecorator(component); 73 | 74 | decoratedComponent->operation("Decorated Component"); 75 | decoratedComponent->addedOperation("Decorated Component"); 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /prototype.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Specify the kinds of objects to create using a prototypical instance, and 7 | * create new objects by copying this prototype. 8 | */ 9 | 10 | /** 11 | * Use the Prototype pattern when a system should be independent of how its 12 | * products are created, composed, and represented; and 13 | * - When the classes to instantiate are specified at run-time, for example, by 14 | * dynamic loading; or 15 | * - To avoid building a class heirarchy of factories that parallels the class 16 | * hierarchy of products; or 17 | * - When instances of a class can have one of only a few different combinations 18 | * of state. It may be more convenient to install a corresponding number of 19 | * prototypes and clone them rather than instantiating the class manually, 20 | * each time with the appropriate state. 21 | */ 22 | 23 | /* 24 | * The Prototype declares an interface for cloning itself. 25 | */ 26 | typedef struct Prototype_s Prototype_t; 27 | 28 | struct Prototype_s { 29 | Prototype_t *self; 30 | 31 | /* 32 | * Cloning will actually return a copy of itself 33 | */ 34 | Prototype_t *(*clone)(Prototype_t *); 35 | 36 | void (*operation)(Prototype_t *); 37 | }; 38 | 39 | Prototype_t *newPrototype(void (*o)(Prototype_t *)); 40 | 41 | Prototype_t *prototypeClone(Prototype_t *original) 42 | { 43 | Prototype_t *clonedPrototype = newPrototype(original->operation); 44 | 45 | return clonedPrototype; 46 | } 47 | 48 | Prototype_t *newPrototype(void (*o)(Prototype_t *)) 49 | { 50 | Prototype_t *p = (Prototype_t *) malloc(sizeof(Prototype_t)); 51 | 52 | p->self = p; 53 | 54 | p->clone = prototypeClone; 55 | p->operation = o; 56 | 57 | return p; 58 | } 59 | 60 | void operation(Prototype_t *prototype) 61 | { 62 | Prototype_t *p = prototype->clone(prototype); 63 | 64 | p->operation(p); 65 | } 66 | 67 | void op1(Prototype_t *p) { 68 | printf("Prototype 1 (address = %x) operation\n", p); 69 | } 70 | 71 | void op2(Prototype_t *p) { 72 | printf("Prototype 2 (address = %x) operation\n", p); 73 | } 74 | 75 | int main(void) 76 | { 77 | /* 78 | * We have to concrete prototypes (p1 and p2) that do different things. 79 | * These are the tools that we have available to do various operations. 80 | */ 81 | Prototype_t *p1 = newPrototype(op1); 82 | Prototype_t *p2 = newPrototype(op2); 83 | 84 | /* 85 | * Let's do some work with concrete prototype p1, followed by p2, notice 86 | * that the operation only cares that it's working on a prototype type. 87 | */ 88 | operation(p1); 89 | operation(p2); 90 | operation(p2); 91 | operation(p2); 92 | 93 | printf("Notice that the address for p2 is different each time\n"); 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /factory-method.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Define an interface for creating an object, but let subclasses decide which 7 | * class to instantiate. Factory Method lets a class defer instantiation to 8 | * subclasses. 9 | */ 10 | 11 | /** 12 | * Use the Factory Method pattern when 13 | * - A class can't anticipate the class of objects it must create. 14 | * - A class wants its subclasses to specify the objects it creates. 15 | * - Classes delegate responsibility to one of several helper subclasses, and 16 | * you want to localize the knowledge of which helper subclass is the 17 | * delegate. 18 | */ 19 | 20 | /* 21 | * The Product defines the interface of objects the factory method creates, and 22 | * a concrete instance implements the Product interface. 23 | */ 24 | typedef struct Product_s Product_t; 25 | 26 | /* 27 | * An abstract class of the Creator declares the factory method, which returns 28 | * an object of type Product, and a concrete version overrides the factory 29 | * method to return an instance of a concrete Product. 30 | */ 31 | typedef struct Creator_s Creator_t; 32 | 33 | struct Product_s { 34 | void (*operation)(Product_t *); 35 | }; 36 | 37 | struct Creator_s { 38 | Product_t *(*factoryMethod)(void); 39 | }; 40 | 41 | Creator_t * newCreator(Product_t *(*factoryMethod)(void), 42 | const char *productStr) 43 | { 44 | Creator_t *creator = (Creator_t *) malloc(sizeof(Creator_t)); 45 | 46 | creator->factoryMethod = factoryMethod; 47 | 48 | printf("Concrete creator set for Product %s\n", productStr); 49 | 50 | return creator; 51 | } 52 | 53 | void operationProductA(Product_t *product) 54 | { 55 | printf("Product A operation\n"); 56 | } 57 | 58 | Product_t * newProductA(void) 59 | { 60 | Product_t *product = (Product_t *) malloc(sizeof(Product_t)); 61 | 62 | product->operation = operationProductA; 63 | 64 | return product; 65 | } 66 | 67 | void operationProductB(Product_t *product) 68 | { 69 | printf("Product B operation\n"); 70 | } 71 | 72 | Product_t * newProductB(void) 73 | { 74 | Product_t *product = (Product_t *) malloc(sizeof(Product_t)); 75 | 76 | product->operation = operationProductB; 77 | 78 | return product; 79 | } 80 | 81 | int main(void) 82 | { 83 | Creator_t *creator; 84 | Product_t *product; 85 | 86 | creator = newCreator(newProductA, "A"); 87 | product = creator->factoryMethod(); 88 | 89 | product->operation(product); 90 | 91 | free(creator); 92 | free(product); 93 | 94 | creator = newCreator(newProductB, "B"); 95 | product = creator->factoryMethod(); 96 | 97 | product->operation(product); 98 | 99 | free(creator); 100 | free(product); 101 | 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /template-method.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Define the skeleton of an algorithm in an operation, deferring some steps 7 | * to subclasses. Template Method lets subclasses redefine certain steps of an 8 | * algorithm without changing the algorithm's structure. 9 | */ 10 | 11 | /** 12 | * Use the Template Method pattern 13 | * - To implement the invariant parts of an algorithm once and leave it up to 14 | * subclasses to implement the behavior that can vary. 15 | * - When common behavior among subclasses should be factored and localized in 16 | * a common class to avoid code duplication. This is a good example of 17 | * "refactoring to generalize". You first identify the differences in the 18 | * existing code and then separate the differences into new operations. 19 | * Finally, you replace the differing code with a template method that calls 20 | * one of these new operations. 21 | * - To control subclasses extensions. You can define a template method that 22 | * calls "hook" operations at specific points, thereby permitting extensions 23 | * only at those points. 24 | */ 25 | 26 | /* 27 | * An abstract instance of this class defines the abstract primitive operations 28 | * that concrete subclasses define to implement steps of an algorithm. It 29 | * implements a template method defining the skeleton of an algorithm, and the 30 | * template method in turn calls primitive operations. 31 | * 32 | * A concrete instance of this class implements the primitive operations to 33 | * carry out subclass-specific steps of the algorithm. 34 | */ 35 | typedef struct Class_s Class_t; 36 | 37 | struct Class_s { 38 | void (*templateMethod)(Class_t *); 39 | 40 | void (*operation1)(void); 41 | void (*operation2)(void); 42 | }; 43 | 44 | Class_t * newClass(void (*templateMethod)(Class_t *), 45 | void (*operation1)(void), 46 | void (*operation2)(void)) 47 | { 48 | Class_t *c = (Class_t *) malloc(sizeof(Class_t)); 49 | 50 | c->templateMethod = templateMethod; 51 | c->operation1 = operation1; 52 | c->operation2 = operation2; 53 | 54 | return c; 55 | } 56 | 57 | void templateMethod(Class_t *c) 58 | { 59 | printf("Running template method: \n"); 60 | c->operation1(); 61 | c->operation2(); 62 | } 63 | 64 | void a1(void) { printf("Primitive Operation A1\n"); } 65 | void a2(void) { printf("Primitive Operation A2\n"); } 66 | void b1(void) { printf("Primitive Operation B1\n"); } 67 | void b2(void) { printf("Primitive Operation B2\n"); } 68 | 69 | int main(void) 70 | { 71 | Class_t *abstractClass = newClass(templateMethod, NULL, NULL); 72 | 73 | Class_t *concreteClassA = newClass(NULL, a1, a2); 74 | Class_t *concreteClassB = newClass(NULL, b1, b2); 75 | 76 | abstractClass->templateMethod(concreteClassA); 77 | 78 | abstractClass->templateMethod(concreteClassB); 79 | 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /chain-of-responsibility.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Intent 7 | * - Avoid coupling the sender of a request to its receiver by giving more than 8 | * one object a chance to handle the request. Chain the receiving objects and 9 | * pass the request along the chain until an object handles it. 10 | */ 11 | 12 | /** 13 | * Use Chain of Responsibility when 14 | * - More than one object may handle a request, and the handler isn't known 15 | * a priori. The handler should be ascertained automatically. 16 | * - You want to issue a request to one of several objects without specifying 17 | * the receiver explicitly. 18 | * - The set of objects that can handle a request should be specified 19 | * dynamically. 20 | */ 21 | 22 | /* 23 | * The Handler handles requests it is responsible for, and it can access its 24 | * successor. If the concrete handler can handle the request, it does so; 25 | * otherwise it forwards the request to its successor. 26 | */ 27 | typedef struct Handler_s Handler_t; 28 | 29 | struct Handler_s { 30 | const char *id; 31 | const Handler_t *successor; 32 | const char *responsibility; 33 | 34 | void (*handleRequest)(const Handler_t *, const char *); 35 | }; 36 | 37 | void handlerHandleRequest(const Handler_t *h, const char *request) 38 | { 39 | if (strcmp(h->responsibility, request) == 0) { 40 | /* If the request is this handler's responsibility, then handle it */ 41 | printf("Request '%s' handled by '%s'\n", request, h->id); 42 | } else if (h->successor) { 43 | /* Else, just pass it off to the successor, if it has one */ 44 | h->successor->handleRequest(h->successor, request); 45 | } else { 46 | /* Finally, I have no successor, we can't handle the request! */ 47 | 48 | printf("No handler for the request '%s'!\n", request); 49 | } 50 | } 51 | 52 | Handler_t *newHandler(const char *id, 53 | const char *responsibility, 54 | const Handler_t *successor) 55 | { 56 | Handler_t *this = (Handler_t *) malloc(sizeof(Handler_t)); 57 | 58 | this->id = id; 59 | this->responsibility = responsibility; 60 | this->successor = successor; 61 | 62 | this->handleRequest = handlerHandleRequest; 63 | 64 | return this; 65 | } 66 | 67 | int main(void) 68 | { 69 | /* Handler chain: a -> b -> c */ 70 | Handler_t *thirdHandler = newHandler("Third handler", "ghi", NULL); 71 | Handler_t *secondHandler = newHandler("Second Handler", "def", thirdHandler); 72 | Handler_t *firstHandler = newHandler("First Handler", "abc", secondHandler); 73 | 74 | Handler_t *handler = firstHandler; 75 | 76 | /* Handled by the 'Second Handler' */ 77 | handler->handleRequest(handler, "def"); 78 | 79 | /* Handled by the 'Third Handler' */ 80 | handler->handleRequest(handler, "ghi"); 81 | 82 | /* Handled by the 'First Handler' */ 83 | handler->handleRequest(handler, "abc"); 84 | 85 | /* Handled by no one! */ 86 | handler->handleRequest(handler, "xyz"); 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /bridge.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Decouple an abstraction from its implementation so that the two can vary 7 | * independently. 8 | */ 9 | 10 | /** 11 | * Use the Bridge pattern when 12 | * - You want to avoid a permanent binding between an abstraction and its 13 | * implementation. This might be the case, for example, when the 14 | * implementation must be selected or switched at run-time. 15 | * - Both the abstractions and their implementations should be extensible by 16 | * subclassing. In this case, the Bridge pattern lets you combine the 17 | * different abstractions and implementations and extend them independently. 18 | * - Changes in the implementation of an abstraction should have no impact on its 19 | * clients; that is, their code should not have to be recompiled. 20 | */ 21 | 22 | void impAOperation(void) 23 | { 24 | printf("Implementation A's concrete operation\n"); 25 | } 26 | 27 | void impBOperation(void) 28 | { 29 | printf("Implementation B's concrete operation\n"); 30 | } 31 | 32 | /* 33 | * Implementor 34 | */ 35 | typedef struct Implementor_s { 36 | void (*operation)(void); 37 | void (*setImplementation)(struct Implementor_s *imp, 38 | struct Implementor_s *concreteImp); 39 | } Implementor_t; 40 | 41 | void setImplementation(Implementor_t *this, Implementor_t *concreteImp) 42 | { 43 | this->operation = concreteImp->operation; 44 | } 45 | 46 | Implementor_t *newImplementor(void (*operation)(void)) 47 | { 48 | Implementor_t *imp = (Implementor_t *) malloc(sizeof(Implementor_t)); 49 | 50 | imp->operation = operation; 51 | imp->setImplementation = setImplementation; 52 | 53 | return imp; 54 | } 55 | 56 | /* 57 | * Abstraction 58 | */ 59 | typedef struct Abstraction_s { 60 | Implementor_t *imp; 61 | void (*operation)(struct Abstraction_s *abs); 62 | } Abstraction_t; 63 | 64 | /* 65 | * Notice that the abstraction does not care about how the operation gets 66 | * implemented. 67 | */ 68 | void absOperation(Abstraction_t *abs) 69 | { 70 | Implementor_t *imp = abs->imp; 71 | 72 | /* 73 | * Here it's goingt to call the implementation specific operation. 74 | */ 75 | imp->operation(); 76 | } 77 | 78 | Abstraction_t *newAbstraction(Implementor_t *imp) 79 | { 80 | Abstraction_t *abs 81 | = (Abstraction_t *) malloc(sizeof(Abstraction_t)); 82 | 83 | /* 84 | * THIS IS THE BRIDGE 85 | * 86 | * The abstraction only has a reference to the implementation. When it calls 87 | * particular functions, it doesn't know the implementation specific 88 | * details. 89 | */ 90 | abs->imp = imp; 91 | abs->operation = absOperation; 92 | 93 | return abs; 94 | } 95 | 96 | int main(void) 97 | { 98 | Implementor_t *imp = newImplementor(NULL); 99 | Abstraction_t *abs = newAbstraction(imp); 100 | 101 | Implementor_t *concreteImpA = newImplementor(impAOperation); 102 | Implementor_t *concreteImpB = newImplementor(impBOperation); 103 | 104 | imp->setImplementation(imp, concreteImpA); 105 | abs->operation(abs); 106 | 107 | imp->setImplementation(imp, concreteImpB); 108 | abs->operation(abs); 109 | 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /proxy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Provide a surrogate or placeholder for another object to control access to 7 | * it. 8 | */ 9 | 10 | /** 11 | * Use the Proxy pattern when 12 | * - There is a need for a more versatile or sophisticated reference to an 13 | * object than a simple pointer. Several common situations in which the Proxy 14 | * pattern is applicable: 15 | * 1. *remote reference* provides a local representative for an object in 16 | * a different address space. 17 | * 2. *virtual proxy* creates expensive objects on demand. 18 | * 3. *protection proxy* controls access to the original object. Protection 19 | * proxies are useful when objects should have different access rights. 20 | * 4. *smart reference* is a replacement for a bare point that performs 21 | * additional actions when an object is accessed. Typical uses include: 22 | * - counting the number of references to the real object so that it 23 | * can be freed automatically when there are no more references (also 24 | * called 'smart pointers') 25 | * - loading a persistent object into memory when it's first 26 | * referenced. 27 | * - checking that the real object is locked before it's accessed to 28 | * ensure that no other object can change it. 29 | */ 30 | 31 | typedef struct Subject_s Subject_t; 32 | 33 | struct Subject_s { 34 | struct Subject_s *realRef; 35 | 36 | void (*request)(Subject_t *); 37 | }; 38 | 39 | void realRequest(Subject_t *subject) 40 | { 41 | printf("Real request\n"); 42 | } 43 | 44 | Subject_t * newSubject(void) 45 | { 46 | Subject_t *s = (Subject_t *) malloc(sizeof(Subject_t)); 47 | 48 | s->realRef = s; /* real subjects reference is itself */ 49 | 50 | s->request = realRequest; 51 | 52 | return s; 53 | } 54 | 55 | void proxyRequest(Subject_t *proxy) 56 | { 57 | printf("Proxy request\n"); 58 | 59 | if (proxy->realRef == NULL) { 60 | printf("Real subject doesn't exist, created real subject...\n"); 61 | proxy->realRef = newSubject(); 62 | } 63 | 64 | proxy->realRef->request(proxy->realRef); 65 | } 66 | 67 | Subject_t * newProxy(Subject_t *realRef) 68 | { 69 | Subject_t *proxy = (Subject_t *) malloc(sizeof(Subject_t)); 70 | 71 | proxy->realRef = realRef; 72 | proxy->request = proxyRequest; 73 | 74 | return proxy; 75 | } 76 | 77 | int main(void) 78 | { 79 | /* 80 | * The real object that a proxy represents. 81 | */ 82 | Subject_t *realSubject = NULL; 83 | 84 | /* 85 | * The Proxy maintains a reference that lets the proxy access the real 86 | * subject. It also has an interface identical to realSubject, so that the 87 | * proxy can be substituted for the real subject. 88 | * 89 | * It controls access to the real subject and may be responsible for 90 | * creating and deleting it. 91 | */ 92 | Subject_t *proxy = newProxy(realSubject); 93 | 94 | /* At this point, we haven't created any objects... It's not until we use 95 | * the proxy that we'll create the object */ 96 | printf("FIRST REQUEST\n"); 97 | proxy->request(proxy); 98 | 99 | /* No new objects get created, and we simply do the request again */ 100 | printf("SECOND REQUEST\n"); 101 | proxy->request(proxy); 102 | 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /abstract-factory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* for strcmp */ 4 | 5 | /** 6 | * Intent 7 | * - Provide an interface for creating families of related or dependent objects 8 | * without specifying their concrete classes. 9 | */ 10 | 11 | /** 12 | * Use the Abstract Factory pattern when 13 | * - A system should be independent of how its products are created, composed, 14 | * and represented. 15 | * - A system should be configured with one of multiplie families of products. 16 | * - A family of related product objects is designed to be used together, and 17 | * you need to enforce this constraint. 18 | * - You want to provide a class library of products, and you want to reveal 19 | * just their interfaces, not their implementations. 20 | */ 21 | 22 | /* 23 | * Product-related functions 24 | */ 25 | const char *PRODUCT_A_ID = "ALPHA"; 26 | const char *PRODUCT_B_ID = "BETA"; 27 | 28 | typedef struct Product_s { 29 | const char *id; 30 | void (*action)(struct Product_s *product); 31 | } Product_t; 32 | 33 | void productAction(Product_t *product) 34 | { 35 | printf("Product %s\n", product->id); 36 | } 37 | 38 | void destroyProduct(Product_t *product) 39 | { 40 | if (product) { 41 | free(product); 42 | } 43 | } 44 | 45 | /* 46 | * Factory-related functions 47 | */ 48 | typedef struct Factory_s { 49 | Product_t *(*createProduct)(void); 50 | } AbstractFactory_t; 51 | 52 | Product_t *createProductA(void) 53 | { 54 | Product_t *productA = (Product_t *) malloc(sizeof(Product_t)); 55 | 56 | productA->id = PRODUCT_A_ID; 57 | 58 | productA->action = productAction; 59 | 60 | return productA; 61 | } 62 | 63 | Product_t *createProductB(void) 64 | { 65 | Product_t *productB = (Product_t *) malloc(sizeof(Product_t)); 66 | 67 | productB->id = PRODUCT_B_ID; 68 | 69 | productB->action = productAction; 70 | 71 | return productB; 72 | } 73 | 74 | AbstractFactory_t *newProductAFactory(void) 75 | { 76 | AbstractFactory_t *factory 77 | = (AbstractFactory_t *) malloc(sizeof(AbstractFactory_t)); 78 | 79 | factory->createProduct = createProductA; 80 | 81 | return factory; 82 | } 83 | 84 | AbstractFactory_t *newProductBFactory(void) 85 | { 86 | AbstractFactory_t *factory 87 | = (AbstractFactory_t *) malloc(sizeof(AbstractFactory_t)); 88 | 89 | factory->createProduct = createProductB; 90 | 91 | return factory; 92 | } 93 | 94 | /* 95 | * Passing in the product type is just a hack to select the "concrete subclass" 96 | * of the factory. 97 | */ 98 | AbstractFactory_t *newFactory(const char *product) 99 | { 100 | AbstractFactory_t *factory = 0; 101 | 102 | if (strcmp(product, "Product A") == 0) { 103 | factory = newProductAFactory(); 104 | } else if (strcmp(product, "Product B") == 0) { 105 | factory = newProductBFactory(); 106 | } 107 | 108 | return factory; 109 | } 110 | 111 | void destroyFactory(AbstractFactory_t *factory) 112 | { 113 | if (factory) { 114 | free(factory); 115 | } 116 | } 117 | 118 | int main(void) 119 | { 120 | AbstractFactory_t *factory; 121 | Product_t *p; 122 | 123 | /* 124 | * First create Product A 125 | */ 126 | factory = newFactory("Product A"); 127 | p = factory->createProduct(); 128 | 129 | p->action(p); 130 | 131 | destroyProduct(p); 132 | destroyFactory(factory); 133 | 134 | /* 135 | * Next create Product B 136 | */ 137 | factory = newFactory("Product B"); 138 | p = factory->createProduct(); 139 | 140 | p->action(p); 141 | 142 | destroyProduct(p); 143 | destroyFactory(factory); 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /adapter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Intent 7 | * - Convert the interface of a class into another interface clients expect. 8 | * Adapter lets classes work together that couldn't otherwise because of 9 | * incompatible interfaces. 10 | */ 11 | 12 | /** 13 | * Use the Adapter pattern when 14 | * - You want to use an existing class, and its interface does not match the one 15 | * you need. 16 | * - You want to create a reusable class that cooperates with unrelated or 17 | * unforeseen classes, that is, classes that don't necessarily have compatible 18 | * interfaces. 19 | * - (object adapter only) You need to use several existing subclasses, but it's 20 | * impractical to adapt their interface by subclassing every one. An object 21 | * adapter can adapt the interface of its parent class. 22 | */ 23 | 24 | typedef struct Adaptee_s Adaptee_t; 25 | typedef struct Adapter_s Adapter_t; 26 | 27 | /* 28 | * The Adaptee is the object that has an incompatible interface that needs 29 | * adapting for our interface. 30 | */ 31 | #define MAX_STR_LEN 20 32 | struct Adaptee_s { 33 | char strbuf[MAX_STR_LEN]; 34 | void (*storeText)(Adaptee_t *, const char *); 35 | void (*printText)(Adaptee_t *); 36 | }; 37 | 38 | /* 39 | * The Adapter adapts the interface of the Adaptee for the client 40 | * 41 | * Technically, the adapter should be a subclass of a generic Target class that 42 | * defines the domain-specific interface that a client uses. 43 | * 44 | * Let's pretend that the client only understand how to use the 'request' 45 | * method. In this example, the 'request' method is to display text. 46 | */ 47 | struct Adapter_s { 48 | Adaptee_t *adaptee; 49 | 50 | void (*displayText)(Adapter_t *, const char *); 51 | }; 52 | typedef Adapter_t Target_t; 53 | 54 | void adapteeStoreText(Adaptee_t *adaptee, const char *text) 55 | { 56 | strncpy(adaptee->strbuf, text, MAX_STR_LEN); 57 | } 58 | 59 | void adapteePrintText(Adaptee_t *adaptee) 60 | { 61 | printf("%s\n", adaptee->strbuf); 62 | } 63 | 64 | Adaptee_t *newAdaptee(void) 65 | { 66 | Adaptee_t *adaptee = (Adaptee_t *) malloc(sizeof(Adaptee_t)); 67 | 68 | adaptee->storeText = adapteeStoreText; 69 | adaptee->printText = adapteePrintText; 70 | 71 | return adaptee; 72 | } 73 | 74 | void adapterDisplayText(Adapter_t *adapter, const char * text) 75 | { 76 | Adaptee_t *adaptee = adapter->adaptee; 77 | 78 | printf("text: "); 79 | adaptee->storeText(adaptee, text); 80 | adaptee->printText(adaptee); 81 | } 82 | 83 | void unadaptedDisplayText(Target_t *target, const char * text) 84 | { 85 | printf("text: %s\n", text); 86 | } 87 | 88 | Target_t *newTarget(void) 89 | { 90 | Target_t *target = (Target_t *) malloc(sizeof(Target_t)); 91 | 92 | target->displayText = unadaptedDisplayText;; 93 | target->adaptee = NULL; 94 | 95 | return target; 96 | } 97 | 98 | Adapter_t *newAdapter(Adaptee_t *adaptee) 99 | { 100 | Adapter_t *adapter = (Adapter_t *) malloc(sizeof(Adapter_t)); 101 | 102 | adapter->displayText = adapterDisplayText; 103 | adapter->adaptee = adaptee; 104 | 105 | return adapter; 106 | } 107 | 108 | int main(void) 109 | { 110 | Adaptee_t *adaptee = newAdaptee(); 111 | Target_t *unadaptedTarget = (Target_t *) newTarget(); 112 | Target_t *adaptedTarget = (Target_t *) newAdapter(adaptee); 113 | 114 | unadaptedTarget->displayText(unadaptedTarget, "UNADAPTED TARGET"); 115 | 116 | /* 117 | * Pretending that the client only understands how to do a 'request', which 118 | * is a method the Adaptee doesn't have. 119 | */ 120 | adaptedTarget->displayText(adaptedTarget, "ADAPTED TARGET"); 121 | 122 | return 0; 123 | } 124 | -------------------------------------------------------------------------------- /facade.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Provide a unified interface to a set of interfaces in a subsystem. Facade 7 | * defines a higher-level interface that makes the subsystem easier to use. 8 | */ 9 | 10 | /** 11 | * Use the Facade pattern when 12 | * - You want to provide a simple interface to a complex subsystem. Subsystems 13 | * often get more complex as they evolve. Most patterns, when applied, result 14 | * in more and smaller classes. This makes the subsystem more reusable and 15 | * easier to customize, but it also becomes harder to use for clients that 16 | * don't need to customize it. A facade can provide a simple default view of 17 | * the subsystem that is good enough for most clients. Only clients needing 18 | * more customizability will need to look beyond the facade. 19 | * - There are many dependencies between clients and the implementation classes 20 | * of an abstraction. Introduce a facade to decouple the subsystem from 21 | * clients and other subsystems, thereby promoting subsystem independence and 22 | * portability. 23 | * - You want to layer your subsystems. Use a facade to define an entry point to 24 | * each subsystem level. If subsystems are dependent, then you can simplify 25 | * the dependencies between them by making them communicate with each other 26 | * solely through their facades. 27 | */ 28 | 29 | /* 30 | * The Facade knows which subsystem classes are responsible for a request. It 31 | * delegates client requests to appropriate subsystem objects. 32 | */ 33 | typedef struct Facade_s Facade_t; 34 | 35 | /* 36 | * The Subsystem class implements the subsystem functionality. It handles work 37 | * assigned by the Facade object, yet it does not have any knowledge of the 38 | * facade (i.e. they keep no references to it.) 39 | */ 40 | typedef struct Subsystem_s Subsystem_t; 41 | 42 | struct Facade_s { 43 | Subsystem_t *squarer; 44 | Subsystem_t *displayer; 45 | 46 | void (*squareAndDisplay)(Facade_t *, int); 47 | }; 48 | 49 | struct Subsystem_s { 50 | int (*subsystemFn)(int arg); 51 | }; 52 | 53 | void facadeSquareAndDisplay(Facade_t *facade, int num) 54 | { 55 | int result; 56 | 57 | result = facade->squarer->subsystemFn(num); 58 | 59 | facade->displayer->subsystemFn(result); 60 | } 61 | 62 | Facade_t * newFacade(Subsystem_t *squarer, Subsystem_t *displayer) 63 | { 64 | Facade_t *facade = (Facade_t *) malloc(sizeof(Facade_t)); 65 | 66 | facade->squarer = squarer; 67 | facade->displayer = displayer; 68 | 69 | /* 70 | * The new reduce common interface. 71 | */ 72 | facade->squareAndDisplay = facadeSquareAndDisplay; 73 | 74 | return facade; 75 | } 76 | 77 | Subsystem_t * newSubsystem(int (*subsystemFn)(int)) 78 | { 79 | Subsystem_t *subsystem = (Subsystem_t *) malloc(sizeof(Subsystem_t)); 80 | 81 | subsystem->subsystemFn = subsystemFn; 82 | 83 | return subsystem; 84 | } 85 | 86 | int computeOperation(int arg) 87 | { 88 | printf("Calling square operation\n"); 89 | return arg * arg; 90 | } 91 | 92 | int displayOperation(int arg) 93 | { 94 | printf("Calling display operation\n"); 95 | printf("%d\n", arg); 96 | } 97 | 98 | /* 99 | * The client communicates with the subsystem by sending requests to the Facade. 100 | */ 101 | int main(void) 102 | { 103 | /* 104 | * In this example, squarer will not use the displayer subsystem to display 105 | * the results, instead the facade will handle the high-level operation 106 | */ 107 | Subsystem_t *squarer = newSubsystem(computeOperation); 108 | Subsystem_t *displayer = newSubsystem(displayOperation); 109 | 110 | Facade_t *facade = newFacade(squarer, displayer); 111 | 112 | int a = 7; 113 | printf("%d x %d = ...\n", a, a); 114 | 115 | facade->squareAndDisplay(facade, a); 116 | 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /mediator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Intent 7 | * - Define an object that encapsulates how a set of objects interact. Mediator 8 | * promotes loose coupling by keeping objects from referring to each other 9 | * explicitly, and it lets you vary their interaction independently. 10 | * 11 | * The Mediator encapsulates collective behavior. It is responsible for 12 | * controlling and coordinating the interactions of a group of objects. These 13 | * objects only know the mediator, thus reducing the number of 14 | * interconnections. 15 | */ 16 | 17 | /** 18 | * Use the Mediator when 19 | * - A set of objects communicate in well-defined but complex ways. The 20 | * resulting interdependencies are unstructured and difficult to understand. 21 | * - Reusing an object is difficult because it refers to and communicates with 22 | * many other objects. 23 | * - A behavior that's distributed between several classes should be 24 | * customizable without a lot of subclassing. 25 | */ 26 | 27 | /* 28 | * Mediator defines an interface for communicating with Colleague objects 29 | */ 30 | typedef struct Mediator_s Mediator_t; 31 | 32 | /* 33 | * Colleague knows its Mediator object and communicates with its mediator 34 | * whenever it would have otherwise communicated with another Colleague. 35 | * 36 | * They send and receive requests from the Mediator. 37 | */ 38 | typedef struct Colleague_s Colleague_t; 39 | 40 | #define MAX_COLLEAGUES 3 41 | struct Mediator_s { 42 | Colleague_t *colleagues[MAX_COLLEAGUES]; 43 | 44 | void (*addColleague)(Mediator_t *, Colleague_t *); 45 | void (*colleagueUpdate)(Mediator_t *, Colleague_t *); 46 | }; 47 | 48 | #define MAX_ID_LEN 10 49 | struct Colleague_s { 50 | char id[MAX_ID_LEN]; 51 | Mediator_t *mediator; /* gets notified of a change */ 52 | 53 | void (*update)(Colleague_t *c); 54 | }; 55 | 56 | void mediatorAddColleague(Mediator_t *m, Colleague_t *c) 57 | { 58 | for (int k = 0; k < MAX_COLLEAGUES; k++) { 59 | if (m->colleagues[k] == NULL) { 60 | m->colleagues[k] = c; 61 | 62 | printf("COLLEAGUE %s added to MEDIATOR\n", c->id); 63 | break; 64 | } 65 | } 66 | } 67 | 68 | void mediatorColleagueUpdate(Mediator_t *m, Colleague_t *c) 69 | { 70 | printf("MEDIATOR received update from COLLEAGUE %s\n"); 71 | 72 | /* Update all remaining colleagues... */ 73 | for (int k = 0; k < MAX_COLLEAGUES; k++) { 74 | if (c == m->colleagues[k]) { 75 | for (int j = k + 1; j < MAX_COLLEAGUES; j++) { 76 | m->colleagues[j]->update(m->colleagues[j]); 77 | break; 78 | } 79 | } 80 | } 81 | } 82 | 83 | Mediator_t * newMediator(void) 84 | { 85 | Mediator_t *m = (Mediator_t *) malloc(sizeof(Mediator_t)); 86 | 87 | for (int k = 0; k < MAX_COLLEAGUES; k++) { 88 | m->colleagues[k] = NULL; 89 | } 90 | 91 | m->addColleague = mediatorAddColleague; 92 | m->colleagueUpdate = mediatorColleagueUpdate; 93 | 94 | return m; 95 | } 96 | 97 | void colleagueUpdate(Colleague_t *c) 98 | { 99 | printf("COLLEAGUE %s updated\n", c->id); 100 | 101 | c->mediator->colleagueUpdate(c->mediator, c); 102 | } 103 | 104 | Colleague_t * newColleague(const char *id, Mediator_t *m) 105 | { 106 | Colleague_t *c = (Colleague_t *) malloc(sizeof(Colleague_t)); 107 | 108 | strncpy(c->id, id, MAX_ID_LEN); 109 | c->mediator = m; 110 | 111 | c->update = colleagueUpdate; 112 | 113 | m->addColleague(m, c); 114 | 115 | return c; 116 | } 117 | 118 | int main(void) 119 | { 120 | Mediator_t *m = newMediator(); 121 | 122 | Colleague_t *c1 = newColleague("C1", m); 123 | Colleague_t *c2 = newColleague("C2", m); 124 | Colleague_t *c3 = newColleague("C3", m); 125 | 126 | /* 127 | * When C1 updates --> C2 will update 128 | * When C2 updates --> C3 will update 129 | */ 130 | printf("\nExpecting C3 to update ONLY\n"); 131 | c3->update(c3); 132 | 133 | printf("\nExpecting C1, C2, and C3 to update\n"); 134 | c1->update(c1); 135 | 136 | return 0; 137 | } 138 | -------------------------------------------------------------------------------- /flyweight.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Use sharing to support large numbers of fine-grained objects efficiently. 7 | */ 8 | 9 | /** 10 | * The Flyweight pattern's effectiveness depends heavily on how and where it's 11 | * used. Apply the Flyweight pattern when *all* of the following are true: 12 | * - An application uses a large number of objects. 13 | * - Storage costs are high because of the sheer quantity of objects. 14 | * - Most object state can be made extrinsic. 15 | * - Many groups of objects may be replaced by relatively few shared objects 16 | * once extrinsic state is removed. 17 | * - The application doesn't depend on object identity. Since flyweight objects 18 | * may be shared, identity tests will return true for conceptually distinct 19 | * objects. 20 | */ 21 | 22 | /* 23 | * The Flyweight declares an interface through which flyweights can receive and 24 | * act on extrinsic state. 25 | * 26 | * Adds storage for intrinsic state, if any. 27 | */ 28 | typedef struct Flyweight_s Flyweight_t; 29 | 30 | /* 31 | * The FlyweightFactory creates and manages flyweight objects, and ensures that 32 | * flyweights are shared properly. When a client requests a flyweight, the 33 | * FlyweightFactory object supplies an existing instance or creates one, if none 34 | * exists. 35 | */ 36 | typedef struct FlyweightFactory_s FlyweightFactory_t; 37 | 38 | struct Flyweight_s { 39 | int key; 40 | int intState; 41 | int extState; 42 | 43 | void (*operation)(Flyweight_t *, int extState); 44 | }; 45 | 46 | void flyweightOperation(Flyweight_t *fw, int extState) 47 | { 48 | fw->extState = extState; 49 | 50 | /* The intrinsic state differs from the extrinsic state */ 51 | fw->intState = 2*fw->extState; 52 | } 53 | 54 | Flyweight_t * newFlyweight(int key) 55 | { 56 | Flyweight_t *fw = (Flyweight_t *) malloc(sizeof(Flyweight_t)); 57 | 58 | fw->key = key; 59 | 60 | fw->operation = flyweightOperation; 61 | 62 | return fw; 63 | } 64 | 65 | #define FLYWEIGHT_POOL_SIZE 5 66 | struct FlyweightFactory_s { 67 | int numFlyweights; 68 | Flyweight_t *pool[FLYWEIGHT_POOL_SIZE]; 69 | 70 | Flyweight_t *(*getFlyweight)(FlyweightFactory_t *, int); 71 | }; 72 | 73 | Flyweight_t * getFlyweight(FlyweightFactory_t *f, int key) 74 | { 75 | if (f->pool[key]) { 76 | /* flyweight exists */ 77 | return f->pool[key]; 78 | } else if (key < FLYWEIGHT_POOL_SIZE) { 79 | /* flyweight does not yet exist, create it */ 80 | Flyweight_t *fw = newFlyweight(key); 81 | f->pool[key] = fw; 82 | 83 | f->numFlyweights++; 84 | 85 | return f->pool[key]; 86 | } else { 87 | return NULL; 88 | } 89 | } 90 | 91 | FlyweightFactory_t * newFlyweightFactory(void) 92 | { 93 | FlyweightFactory_t *f = (FlyweightFactory_t *) malloc(sizeof(FlyweightFactory_t)); 94 | 95 | f->getFlyweight = getFlyweight; 96 | 97 | return f; 98 | } 99 | 100 | #define MAX_FLYWEIGHTS 10 101 | int main(void) 102 | { 103 | FlyweightFactory_t *f = newFlyweightFactory(); 104 | 105 | Flyweight_t *fw[MAX_FLYWEIGHTS]; 106 | 107 | for (int k = 0; k < MAX_FLYWEIGHTS; k++) { 108 | int key = k % (MAX_FLYWEIGHTS / 2); /* half as many objects */ 109 | 110 | /* In the first half of the loop, flyweights will get created. In the 111 | * next half of the loop, existing flyweights will be retrieved */ 112 | fw[k] = f->getFlyweight(f, key); 113 | 114 | /* 115 | * We are going to pass in k as the 'operation' on the flyweight, 116 | * pretending this is the 'extrinsic state'. 117 | */ 118 | fw[k]->operation(fw[k], k); 119 | } 120 | 121 | printf("Flyweights created: %d\n", f->numFlyweights); 122 | 123 | printf("Flyweights in list:\n"); 124 | 125 | /* 126 | * Display all the flyweights that are referenced in the fw array 127 | */ 128 | for (int k = 0; k < f->numFlyweights; k++) { 129 | printf("Flyweight[%d]: key=%d, intrinsic state=%d, extrinsic state=%d\n", 130 | k, fw[k]->key, fw[k]->intState, fw[k]->extState); 131 | } 132 | 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /observer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Intent 7 | * - Define a one-to-many dependency between objects so that when one object 8 | * changes state, all its dependents are notified and updated automatically. 9 | */ 10 | 11 | /** 12 | * Use the Observer pattern when 13 | * - An abstraction has two aspects, one dependent on the other. Encapsulating 14 | * these aspects in separate objects lets you vary and reuse them 15 | * independently. 16 | * - A change to one object requires changing others, and you don't know how 17 | * many objects need to be changed. 18 | * - An object should be able to notify other objects without making assumptions 19 | * about who these objects are. In other words, you don't want these objects 20 | * tightly coupled. 21 | */ 22 | 23 | typedef enum { 24 | EVENT_1 = 1, 25 | EVENT_2, 26 | EVENT_3, 27 | } Event_t; 28 | 29 | typedef struct Subject_s Subject_t; 30 | typedef struct Observer_s Observer_t; 31 | 32 | #define MAX_OBSERVERS 3 33 | struct Subject_s { 34 | Observer_t *obs[MAX_OBSERVERS]; 35 | 36 | void (*attach)(Subject_t *, Observer_t *); 37 | void (*detach)(Subject_t *, Observer_t *); 38 | void (*notify)(Subject_t *, Event_t e); 39 | }; 40 | 41 | #define MAX_OBSERVER_ID_LEN 10 42 | struct Observer_s { 43 | char id[MAX_OBSERVER_ID_LEN]; 44 | Event_t myEvent; 45 | 46 | void (*update)(Observer_t *, Event_t e); 47 | }; 48 | 49 | void subjectAttach(Subject_t *subject, Observer_t *obs) 50 | { 51 | for (int k = 0; k < MAX_OBSERVERS; k++) { 52 | if (subject->obs[k] == NULL) { 53 | printf("\tSUBJECT attaching OBSERVER_%s\n", obs->id); 54 | 55 | subject->obs[k] = obs; 56 | break; 57 | } 58 | } 59 | } 60 | 61 | void subjectDetach(Subject_t *subject, Observer_t *obs) 62 | { 63 | for (int k = 0; k < MAX_OBSERVERS; k++) { 64 | if (subject->obs[k] == obs) { 65 | printf("\tSUBJECT detaching OBSERVER_%s\n", obs->id); 66 | 67 | subject->obs[k] = NULL; 68 | break; 69 | } 70 | } 71 | } 72 | 73 | void subjectNotify(Subject_t *subject, Event_t e) 74 | { 75 | printf("\tSUBJECT notifying EVENT %u\n", (unsigned) e); 76 | 77 | for (int k = 0; k < MAX_OBSERVERS; k++) { 78 | Observer_t *obs = subject->obs[k]; 79 | 80 | if (obs) { 81 | obs->update(obs, e); 82 | } 83 | } 84 | } 85 | 86 | Subject_t * newSubject(void) 87 | { 88 | Subject_t *subject = (Subject_t *) malloc(sizeof(Subject_t)); 89 | 90 | for (int k = 0; k < MAX_OBSERVERS; k++) { 91 | subject->obs[k] = NULL; 92 | } 93 | 94 | subject->attach = subjectAttach; 95 | subject->detach = subjectDetach; 96 | subject->notify = subjectNotify; 97 | 98 | return subject; 99 | } 100 | 101 | void observerUpdate(Observer_t *obs, Event_t e) 102 | { 103 | /* This gets called from the subject */ 104 | if (obs->myEvent == e) { 105 | printf("\t\tOBSERVER_%s has received the update for EVENT %d\n", 106 | obs->id, e); 107 | } 108 | } 109 | 110 | Observer_t * newObserver(const char *id, Subject_t *subject, Event_t e) 111 | { 112 | Observer_t *observer = (Observer_t *) malloc(sizeof(Observer_t)); 113 | 114 | strncpy(observer->id, id, MAX_OBSERVER_ID_LEN); 115 | observer->myEvent = e; 116 | 117 | observer->update = observerUpdate; 118 | 119 | subject->attach(subject, observer); 120 | 121 | return observer; 122 | } 123 | 124 | int main(void) 125 | { 126 | /* This is the subject of interest to the observers */ 127 | Subject_t *subject = newSubject(); 128 | 129 | Observer_t *observerA = newObserver("A", subject, EVENT_1); 130 | Observer_t *observerB = newObserver("B", subject, EVENT_2); 131 | 132 | printf("Expecting OBSERVER_A to be notified for EVENT_1 (twice)\n"); 133 | printf("Expecting OBSERVER_B to be notified for EVENT_2\n"); 134 | 135 | subject->notify(subject, EVENT_1); 136 | subject->notify(subject, EVENT_1); 137 | subject->notify(subject, EVENT_2); 138 | 139 | subject->detach(subject, observerA); 140 | 141 | printf("Expecting OBSERVER_B to be notified for EVENT_2\n"); 142 | subject->notify(subject, EVENT_1); 143 | subject->notify(subject, EVENT_2); 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /command.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Encapsulate a request as an object, thereby letting you parameterize 7 | * clients with different requests, queue or log requests, and support 8 | * undoable operations. 9 | */ 10 | 11 | /** 12 | * Use the Command pattern when 13 | * - You want to parameterize objects by an action to perform. You can express 14 | * such parameterization in a procedural language with a "callback" function, 15 | * that is a function that's registered somewhere to be called at a later 16 | * point. Commands are an object-oriented replacement for callbacks. 17 | * - You want to specify, queue, and execute requests at different times. A 18 | * Command object can have a lifetime independent of the original request. 19 | * - You want to support undo. The Command's Execute operation can store state 20 | * for reversing its effects in the command itself. The Command interface must 21 | * have an added Unexecute operation that reverses the effects of a previous 22 | * call to Execute. Executed commands are stored in a history list. 23 | * Unlimited-level undo and redo is achieved by traversing this list backwards 24 | * and forwards calling Unexecute and Execute, respectively. 25 | * - You want to support logging changes so that they can be reapplied in case 26 | * of a system crash. By augmenting the Command interface with load and store 27 | * operations, you can keep a persistent log of changes. Recovering from a 28 | * crash involves reloading logged commands from disk and reexecuting them 29 | * with the Execute operation. 30 | * - You want to structure a system around high-level operations built on 31 | * primitives operations. Such a structure is common in information systems 32 | * that support transactions. A transaction encapsulates a set of changes to 33 | * data. The Command pattern offers a way to model transactions. Commands have 34 | * a common interface, letting you invoke all transactions the same way. The 35 | * pattern also makes it easy to extend the system with new transactions. 36 | */ 37 | /* i.e. The object that will execute a command's action */ 38 | typedef struct Receiver_s { 39 | void (*action)(void); 40 | } Receiver_t; 41 | 42 | void receiverAction(void) 43 | { 44 | printf("Receiver action performed!\n"); 45 | } 46 | 47 | Receiver_t * newReceiver(void) 48 | { 49 | Receiver_t *receiver = (Receiver_t *) malloc(sizeof(Receiver_t)); 50 | 51 | receiver->action = receiverAction; 52 | 53 | return receiver; 54 | } 55 | 56 | typedef struct Command_s { 57 | Receiver_t *receiver; 58 | void (*execute)(struct Command_s *command); 59 | } Command_t; 60 | 61 | void commandExecute(Command_t *command) 62 | { 63 | printf("The command is executing, calling the receiver...\n"); 64 | command->receiver->action(); 65 | } 66 | 67 | Command_t * newCommand(Receiver_t *receiver) 68 | { 69 | Command_t *command = (Command_t *) malloc(sizeof(command)); 70 | 71 | command->receiver = receiver; 72 | command->execute = commandExecute; 73 | 74 | return command; 75 | } 76 | 77 | /* i.e. The object that will handle a request */ 78 | typedef struct Invoker_s { 79 | Command_t *requestHandler; 80 | void (*storeCommand)(struct Invoker_s *invoker, Command_t *concreteCommand); 81 | void (*doCommand)(struct Invoker_s *invoker); 82 | } Invoker_t; 83 | 84 | void invokerSetCommand(Invoker_t *invoker, Command_t *concreteCommand) 85 | { 86 | invoker->requestHandler = concreteCommand; 87 | } 88 | 89 | void invokerHandleRequest(Invoker_t *invoker) 90 | { 91 | printf("The invoker has received a request to handle a command...\n"); 92 | invoker->requestHandler->execute(invoker->requestHandler); 93 | } 94 | 95 | Invoker_t * newInvoker(void) 96 | { 97 | Invoker_t *invoker = (Invoker_t *) malloc(sizeof(Invoker_t)); 98 | 99 | invoker->storeCommand = invokerSetCommand; 100 | invoker->doCommand = invokerHandleRequest; 101 | 102 | return invoker; 103 | } 104 | 105 | int main(void) 106 | { 107 | Receiver_t * receiver = newReceiver(); 108 | Command_t * concreteCommand = newCommand(receiver); 109 | Invoker_t * invoker = newInvoker(); 110 | 111 | invoker->storeCommand(invoker, concreteCommand); 112 | 113 | invoker->doCommand(invoker); 114 | 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /state.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* for strncpy */ 4 | 5 | /** 6 | * Intent 7 | * - Allow an object to alter its behavior when its internal state changes. The 8 | * object will appear to change its class. 9 | */ 10 | 11 | /** 12 | * Use the State pattern when 13 | * - An object's behavior depends on its state, and it must change its 14 | * behavior at run-time depending on that state. 15 | * - Operations have large, multipart conditional statements that depend on the 16 | * object's state. This state is usually represented by one or more enumerated 17 | * constants. Often, several operations will contain this same conditional 18 | * structure. The State pattern puts each branch of the conditional in a 19 | * separate class. This lets you treat the object's state as an object in its 20 | * own right that can var independently from other objects. 21 | */ 22 | 23 | #define MAX_STATE_ID 10 24 | 25 | typedef struct State_s State_t; 26 | typedef struct Context_s Context_t; 27 | /* 28 | * Each state has a set of actions it can do at that state, and for the given 29 | * context, it can change the state. 30 | */ 31 | struct State_s { 32 | char id[MAX_STATE_ID]; 33 | 34 | void (*changeState)(Context_t *, State_t *); 35 | State_t *(*action)(Context_t *); 36 | }; 37 | 38 | /* 39 | * Configure context (i.e. whatever it is that is subject to states) 40 | */ 41 | struct Context_s { 42 | State_t *currentState; 43 | State_t *nextState; 44 | State_t *stateX; 45 | State_t *stateY; 46 | State_t *stateZ; 47 | 48 | void (*changeState)(Context_t *, State_t *); 49 | void (*begin)(Context_t *); 50 | void (*end)(Context_t *); 51 | void (*step)(Context_t *); 52 | }; 53 | 54 | void stateChangeState(Context_t *c, State_t *s) 55 | { 56 | State_t *oldState = c->currentState; 57 | State_t *nextState = s->action(c); 58 | State_t *newState = s; 59 | 60 | c->currentState = s; 61 | c->nextState = nextState; 62 | 63 | printf("\tChanged from %s to %s (next is %s)\n", 64 | oldState->id, 65 | newState->id, 66 | nextState->id); 67 | 68 | } 69 | 70 | State_t *newState(char *id, State_t *(*action)(Context_t *)) 71 | { 72 | State_t *s = (State_t *) malloc(sizeof(State_t)); 73 | 74 | strncpy(s->id, id, MAX_STATE_ID); 75 | 76 | s->changeState = stateChangeState; 77 | s->action = action; 78 | 79 | return s; 80 | } 81 | 82 | State_t * actionX(Context_t *c) 83 | { 84 | printf("Doing action X"); 85 | return c->stateY; 86 | } 87 | 88 | State_t * actionY(Context_t *c) 89 | { 90 | printf("Doing action Y"); 91 | return c->stateZ; 92 | } 93 | 94 | State_t * actionZ(Context_t *c) 95 | { 96 | printf("Doing action Z"); 97 | return c->stateX; 98 | } 99 | 100 | void contextChangeState(Context_t *c, State_t *newState) 101 | { 102 | c->currentState->changeState(c, newState); 103 | } 104 | 105 | void contextBegin(Context_t *c) 106 | { 107 | printf("BEGIN:\t"); 108 | c->changeState(c, c->stateX); 109 | } 110 | 111 | void contextStep(Context_t *c) 112 | { 113 | printf("STEP:\t"); 114 | c->changeState(c, c->nextState); 115 | } 116 | 117 | void contextEnd(Context_t *c) 118 | { 119 | printf("END:\t"); 120 | c->changeState(c, c->stateZ); 121 | } 122 | 123 | Context_t *newContext(State_t *stateX, 124 | State_t *stateY, 125 | State_t *stateZ) 126 | { 127 | Context_t *c = (Context_t *) malloc(sizeof(Context_t)); 128 | 129 | c->currentState = stateX; 130 | c->stateX = stateX; 131 | c->stateY = stateY; 132 | c->stateZ = stateZ; 133 | 134 | c->changeState = contextChangeState; 135 | c->begin = contextBegin; 136 | c->step = contextStep; 137 | c->end = contextEnd; 138 | 139 | return c; 140 | } 141 | 142 | int main(void) 143 | { 144 | /* 145 | * These are the concrete states 146 | */ 147 | State_t *stateX = newState("X", actionX); 148 | State_t *stateY = newState("Y", actionY); 149 | State_t *stateZ = newState("Z", actionZ); 150 | 151 | Context_t *c = newContext(stateX, stateY, stateZ); 152 | 153 | c->begin(c); /* Start at State X */ 154 | 155 | c->step(c); /* State Y */ 156 | c->step(c); /* State Z */ 157 | c->step(c); /* State X */ 158 | c->step(c); /* State Y */ 159 | c->step(c); /* State Z */ 160 | c->step(c); /* State X */ 161 | 162 | c->end(c); /* End at State Z */ 163 | 164 | return 0; 165 | } 166 | -------------------------------------------------------------------------------- /strategy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Define a family of algorithms, encapsulate each one, and make them 7 | * interchangeable. Strategy lets the algorithm vary independently from 8 | * clients that use it. 9 | */ 10 | 11 | /** 12 | * Use the Strategy pattern when 13 | * - many related classes differ only in their behavior. Strategies provide a 14 | * way to configure a class with one of many behaviors. 15 | * - you need different variants of an algorithm. For example, you might define 16 | * algorithms reflecting different space/time trade-offs. Strategies can be 17 | * used when these variants are implemented as a class heirarchy of 18 | * algorithms. 19 | * - an algorithm uses data that clients shouldn't know about. Use the Strategy 20 | * pattern to avoid exposing complex, algorithm-specific data structures. 21 | * - a class defines many behaviors, and these appear as multiple conditional 22 | * statements in its operations. Instead of many conditionals, move related 23 | * conditional branches into their own Strategy class. 24 | */ 25 | 26 | #define MAX_ALGORITHM_NAME_LEN 24 27 | 28 | typedef struct Strategy_s { 29 | /* 30 | * This is the interface to the algorithm 31 | */ 32 | unsigned (*algorithm)(unsigned value1, unsigned value2); 33 | 34 | char name[MAX_ALGORITHM_NAME_LEN]; 35 | } Strategy_t; 36 | 37 | Strategy_t * newStrategy(unsigned (*algorithm)(unsigned, unsigned), 38 | const char * const name) 39 | { 40 | Strategy_t *strategy = (Strategy_t *) malloc(sizeof(Strategy_t)); 41 | 42 | strategy->algorithm = algorithm; 43 | 44 | snprintf(strategy->name, MAX_ALGORITHM_NAME_LEN, name); 45 | 46 | return strategy; 47 | } 48 | 49 | unsigned algorithmA(unsigned value1, unsigned value2) 50 | { 51 | return value1 + value2; 52 | } 53 | 54 | unsigned algorithmB(unsigned value1, unsigned value2) 55 | { 56 | return value1 * value2; 57 | } 58 | 59 | /* 60 | * The context is the class that has a strategy. It can be any type of object, 61 | * as long as it implements a strategy. It also has an interface with which to 62 | * run the strategy. 63 | */ 64 | typedef struct Context_s { 65 | Strategy_t *strategy; 66 | 67 | void (*setStrategy)(struct Context_s *self, Strategy_t *strategy); 68 | void (*runAlgorithm)(struct Context_s *self); 69 | void (*show)(struct Context_s *self); 70 | 71 | unsigned value; 72 | 73 | char algorithmStr[MAX_ALGORITHM_NAME_LEN]; 74 | } Context_t; 75 | 76 | void contextSetStrategy(Context_t *this, Strategy_t *strategy) 77 | { 78 | this->strategy = strategy; 79 | 80 | snprintf(this->algorithmStr, MAX_ALGORITHM_NAME_LEN, strategy->name); 81 | 82 | printf("Set strategy to %s\n", this->algorithmStr); 83 | } 84 | 85 | void contextRunAlgorithm(Context_t *this) 86 | { 87 | this->value = this->strategy->algorithm(this->value, 2); 88 | } 89 | 90 | void contextShow(Context_t *this) 91 | { 92 | printf("Context: Algorithm=%.*s, Value=%u\n", 93 | MAX_ALGORITHM_NAME_LEN, 94 | this->algorithmStr, this->value); 95 | } 96 | 97 | Context_t *newContext(void) 98 | { 99 | Context_t *context = (Context_t *) malloc(sizeof(Context_t)); 100 | 101 | /* 102 | * Methods 103 | */ 104 | context->setStrategy = contextSetStrategy; 105 | context->runAlgorithm = contextRunAlgorithm; 106 | context->show = contextShow; 107 | 108 | /* 109 | * Data 110 | */ 111 | sprintf(context->algorithmStr, ""); 112 | context->value = 0; 113 | 114 | return context; 115 | } 116 | 117 | int main(void) 118 | { 119 | /* 120 | * These are the concrete strategies 121 | */ 122 | Strategy_t *strategyA = newStrategy(algorithmA, "add"); 123 | Strategy_t *strategyB = newStrategy(algorithmB, "multiply"); 124 | 125 | Context_t *context = newContext(); 126 | 127 | /* Add strategy */ 128 | context->setStrategy(context, strategyA); 129 | 130 | context->runAlgorithm(context); 131 | context->show(context); 132 | 133 | context->runAlgorithm(context); 134 | context->show(context); 135 | 136 | context->runAlgorithm(context); 137 | context->show(context); 138 | 139 | /* Multiply strategy */ 140 | context->setStrategy(context, strategyB); 141 | 142 | context->runAlgorithm(context); 143 | context->show(context); 144 | 145 | context->runAlgorithm(context); 146 | context->show(context); 147 | 148 | return 0; 149 | } 150 | -------------------------------------------------------------------------------- /memento.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Without violating encapsulation, capture and externalize an object's 7 | * internal state so that the object can be restored to this state later. 8 | */ 9 | 10 | /** 11 | * Use the Memento pattern when 12 | * - A snapshot of (some portion of) an object's state must be saved so that it 13 | * can be restored to that state later, *and*... 14 | * - A direct interface to obtaining the state would expose implementation 15 | * details and break the object's encapsulation. 16 | */ 17 | 18 | /* 19 | * The Memento stores the internal state of the Originator object. It protects 20 | * against access by objects other than the originator. 21 | */ 22 | typedef struct Memento_s Memento_t; 23 | 24 | /* 25 | * The Originator creates a memento containing a snapshot of its current 26 | * internal state, and it uses the memento to restore its internal state. 27 | */ 28 | typedef struct Originator_s Originator_t; 29 | 30 | /* 31 | * The Caretake is responsible for the memento's safekeeping and never operates 32 | * on or examines the contents of the memento. 33 | */ 34 | typedef struct Caretaker_s Caretaker_t; 35 | 36 | typedef char * State_t; 37 | 38 | struct Memento_s { 39 | State_t state; 40 | 41 | State_t (*getState)(Memento_t *); 42 | void (*setState)(Memento_t *, State_t); 43 | }; 44 | 45 | struct Originator_s { 46 | State_t state; 47 | 48 | void (*setState)(Originator_t *, State_t); 49 | Memento_t *(*createMemento)(Originator_t *); 50 | void (*setMemento)(Originator_t *, Memento_t *); 51 | }; 52 | 53 | #define MAX_MEMENTO_HISTORY 5 54 | struct Caretaker_s { 55 | Memento_t *mHistory[MAX_MEMENTO_HISTORY]; 56 | int mIndex; 57 | Originator_t *originator; 58 | 59 | void (*snapshot)(Caretaker_t *); 60 | void (*rollback)(Caretaker_t *); 61 | }; 62 | 63 | State_t mGetState(Memento_t *m) 64 | { 65 | return m->state; 66 | } 67 | 68 | void mSetState(Memento_t *m, State_t s) 69 | { 70 | m->state = s; 71 | } 72 | 73 | Memento_t * newMemento(void) 74 | { 75 | Memento_t *m = (Memento_t *) malloc(sizeof(Memento_t)); 76 | 77 | m->getState = mGetState; 78 | m->setState = mSetState; 79 | 80 | return m; 81 | } 82 | 83 | void oSetState(Originator_t *o, State_t state) 84 | { 85 | o->state = state; 86 | 87 | printf("ORIGINATOR state: \"%s\"\n", o->state); 88 | } 89 | 90 | Memento_t * oCreateMemento(Originator_t *o) 91 | { 92 | Memento_t *m = newMemento(); 93 | 94 | printf("Creating MEMENTO for \"%s\"\n", o->state); 95 | 96 | /* save the state to the memento */ 97 | m->setState(m, o->state); 98 | 99 | return m; 100 | } 101 | 102 | void oSetMemento(Originator_t *o, Memento_t *m) 103 | { 104 | State_t state = m->getState(m); 105 | 106 | printf("Restoring MEMENTO for \"%s\"\n", state); 107 | 108 | /* restore the state from the memento */ 109 | o->setState(o, state); 110 | } 111 | 112 | Originator_t * newOriginator(void) 113 | { 114 | Originator_t *o = (Originator_t *) malloc(sizeof(Originator_t)); 115 | 116 | o->state = NULL; 117 | 118 | o->setState = oSetState; 119 | 120 | o->createMemento = oCreateMemento; 121 | o->setMemento = oSetMemento; 122 | 123 | return o; 124 | } 125 | 126 | void cSnapshot(Caretaker_t *c) 127 | { 128 | printf("CARETAKER snapshot: "); 129 | 130 | Memento_t *m = c->originator->createMemento(c->originator); 131 | 132 | c->mHistory[++c->mIndex] = m; 133 | } 134 | 135 | void cRollback(Caretaker_t *c) 136 | { 137 | printf("CARETAKER rollback: "); 138 | 139 | Memento_t *m = c->mHistory[--c->mIndex]; 140 | 141 | c->originator->setMemento(c->originator, m); 142 | } 143 | 144 | Caretaker_t * newCaretaker(Originator_t *o) 145 | { 146 | Caretaker_t *c = (Caretaker_t *) malloc(sizeof(Caretaker_t)); 147 | 148 | c->originator = o; 149 | c->mIndex = 0; 150 | 151 | c->snapshot = cSnapshot; 152 | c->rollback = cRollback; 153 | 154 | return c; 155 | } 156 | 157 | int main(void) 158 | { 159 | Originator_t *o = newOriginator(); 160 | Caretaker_t *c = newCaretaker(o); 161 | 162 | o->setState(o, "1st state"); 163 | c->snapshot(c); 164 | 165 | o->setState(o, "2nd state"); 166 | c->snapshot(c); 167 | 168 | o->setState(o, "3rd state"); 169 | c->snapshot(c); 170 | 171 | c->rollback(c); /* expect 2nd state */ 172 | c->rollback(c); /* expect 1st state */ 173 | 174 | o->setState(o, "4th state"); 175 | c->snapshot(c); 176 | 177 | o->setState(o, "5th state"); 178 | printf("NO SNAPSHOT\n"); 179 | 180 | c->rollback(c); /* expect 1st state */ 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /iterator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Intent 7 | * - Provide a way to access the elements of an aggregate object sequentially 8 | * without exposing its underlying representation. 9 | */ 10 | 11 | /** 12 | * Use the Iterator pattern 13 | * - to access an aggregate object's contents without exposing its internal 14 | * representation. 15 | * - to support multiple traversals of aggregate objects. 16 | * - to provide a uniform interface for traversing different aggregate 17 | * structures (that is, to support polymorphic iteration) 18 | */ 19 | 20 | #define MAX_LIST_SIZE 10 21 | typedef struct List_s { 22 | int el[MAX_LIST_SIZE]; 23 | int count; 24 | 25 | void (*append)(struct List_s *, int); 26 | void (*remove)(struct List_s *, int); 27 | 28 | /* 29 | * In order for an aggregate class to support iteration, it must have the 30 | * ability to create an interator. 31 | */ 32 | struct Iterator_s * (*createIterator)(struct List_s *); 33 | } List_t; 34 | 35 | /* 36 | * In this example, we have an aggregate object (e.g. List), but we don't want 37 | * to put the iteration mechanics in its class. Instead, we create a 38 | * ListIterator class that would perform the traversal for a list object. That 39 | * way, we don't need to modify the list object. 40 | */ 41 | typedef struct Iterator_s { 42 | int current; 43 | struct List_s *list; 44 | 45 | void (*first)(struct Iterator_s *); 46 | void (*next)(struct Iterator_s *); 47 | bool (*isDone)(struct Iterator_s *); 48 | int (*currentItem)(struct Iterator_s *); 49 | } Iterator_t; 50 | 51 | void iteratorFirst(Iterator_t *iter) 52 | { 53 | iter->current = 0; 54 | } 55 | 56 | void iteratorNext(Iterator_t *iter) 57 | { 58 | iter->current++; 59 | } 60 | 61 | bool iteratorIsDone(Iterator_t *iter) 62 | { 63 | return iter->current >= iter->list->count; 64 | } 65 | 66 | int iteratorCurrentItem(Iterator_t *iter) 67 | { 68 | if (!iter->isDone(iter)) { 69 | return iter->list->el[iter->current]; 70 | } else { 71 | /* No exception handling. Simply denote -1 as out of bounds. */ 72 | return -1; 73 | } 74 | } 75 | 76 | Iterator_t * newIterator(struct List_s *list) 77 | { 78 | Iterator_t *iter = (Iterator_t *) malloc(sizeof(Iterator_t)); 79 | 80 | iter->current = 0; 81 | iter->list = list; 82 | 83 | iter->first = iteratorFirst; 84 | iter->next = iteratorNext; 85 | iter->isDone = iteratorIsDone; 86 | iter->currentItem = iteratorCurrentItem; 87 | 88 | return iter; 89 | } 90 | 91 | /* 92 | * This is the aggregate class. In this example, it's a simple array list. 93 | * 94 | * The responsibilities of this class are simple. You may simply add an element 95 | * into it, remove an element, and count the number of elements. There is no 96 | * "traversal" or "iterating" mechanism built in. For that, we will create a 97 | * ListIterator subclass. 98 | */ 99 | typedef struct ListIterator_s { 100 | List_t *list; 101 | int current; 102 | 103 | void (*first)(struct Iterator_s *); 104 | void (*next)(struct Iterator_s *); 105 | bool (*isDone)(struct Iterator_s *); 106 | void *(*currentItem)(struct Iterator_s *); 107 | } ListIterator_t; 108 | 109 | void listAppend(List_t * list, int el) 110 | { 111 | list->el[list->count++] = el; 112 | } 113 | 114 | void listRemove(List_t * list, int el) 115 | { 116 | /* Remove the first instance of 'el' */ 117 | for (int k = 0; k < list->count; k++) { 118 | if (list->el[k] == el) { 119 | /* Move the remaining elements 'back' */ 120 | int j; 121 | for (j = 0; j < MAX_LIST_SIZE - 1; j++) { 122 | list->el[k+j] = list->el[k+j+1]; 123 | } 124 | list->el[j] = 0; 125 | list->count--; 126 | 127 | break; 128 | } 129 | } 130 | } 131 | 132 | List_t * newList(void) 133 | { 134 | List_t *list = (List_t *) malloc(sizeof(List_t)); 135 | 136 | list->count = 0; 137 | list->append = listAppend; 138 | list->remove = listRemove; 139 | list->createIterator = newIterator; 140 | 141 | return list; 142 | } 143 | 144 | int main(void) 145 | { 146 | List_t *list = newList(); 147 | 148 | list->append(list, 0); 149 | list->append(list, 1); 150 | list->append(list, 2); 151 | list->append(list, 3); 152 | 153 | list->remove(list, 0); 154 | 155 | Iterator_t *listIterator = list->createIterator(list); 156 | 157 | /* Print all the list contents */ 158 | int k = 0; 159 | for (listIterator->first(listIterator); 160 | !listIterator->isDone(listIterator); 161 | listIterator->next(listIterator)) { 162 | printf("list[%d] is '%d'\n", k++, 163 | listIterator->currentItem(listIterator)); 164 | } 165 | 166 | return 0; 167 | } 168 | -------------------------------------------------------------------------------- /visitor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Intent 7 | * - Represent an operation to be performed on the elements of an object 8 | * structure. Visitor lets you define a new operation without changing the 9 | * classes of the elements on which it operates. 10 | */ 11 | 12 | /** 13 | * Use the Visitor pattern when 14 | * - An object structure contains many classes of objects with differing 15 | * interfaces, and you want to perform operations on these objects that depend 16 | * on their concrete classes. 17 | * - Many distinct and unrelated operations need to be performed on objects in 18 | * an object structure, and you want to avoid "polluting" their classes with 19 | * these operations. Visitor lets you keep related operations together by 20 | * defining them in one class. When the object structure is shared by many 21 | * applications, use Visitor to put operations in just those applications that 22 | * need them. 23 | * - The classes defining the object structure rarely change, but you often want 24 | * to define new operations over the structure. Changing the object structure 25 | * classes requires redefining the interface to all visitors, which is 26 | * potentially costly. If the object structure classes change often, then it's 27 | * probably better to define the operations in those classes. 28 | */ 29 | 30 | #define SIZE 10 31 | 32 | typedef struct ElementA_s ElementA_t; 33 | typedef struct ElementB_s ElementB_t; 34 | typedef struct Visitor_s Visitor_t; 35 | 36 | struct ElementA_s { 37 | int num[SIZE]; 38 | int (*accept)(ElementA_t *, Visitor_t *); 39 | }; 40 | 41 | struct ElementB_s { 42 | char string[SIZE]; 43 | int (*accept)(ElementB_t *, Visitor_t *); 44 | }; 45 | 46 | struct Visitor_s { 47 | int (*visitElementA)(Visitor_t *, ElementA_t *); 48 | int (*visitElementB)(Visitor_t *, ElementB_t *); 49 | 50 | /* 51 | * This function will change what the visitor does (poor man's subclassing) 52 | */ 53 | int (*operation)(int *); 54 | }; 55 | 56 | int acceptVisitorElementA(ElementA_t *elemA, Visitor_t *v) 57 | { 58 | return v->visitElementA(v, elemA); 59 | } 60 | 61 | ElementA_t * newElementA(void) 62 | { 63 | ElementA_t *elemA = (ElementA_t *) malloc(sizeof(ElementA_t)); 64 | 65 | for (int k = 0; k < SIZE; k++) { 66 | elemA->num[k] = k; 67 | } 68 | 69 | elemA->accept = acceptVisitorElementA; 70 | 71 | return elemA; 72 | } 73 | 74 | int acceptVisitorElementB(ElementB_t *elemB, Visitor_t *v) 75 | { 76 | return v->visitElementB(v, elemB); 77 | } 78 | 79 | ElementB_t * newElementB(void) 80 | { 81 | ElementB_t *elemB = (ElementB_t *) calloc(SIZE, sizeof(ElementB_t)); 82 | 83 | strncpy(elemB->string, "ABC", SIZE); 84 | 85 | elemB->accept = acceptVisitorElementB; 86 | 87 | return elemB; 88 | } 89 | 90 | int visitElementA(Visitor_t *v, ElementA_t *elemA) 91 | { 92 | return v->operation(elemA->num); 93 | } 94 | 95 | int visitElementB(Visitor_t *v, ElementB_t *elemB) 96 | { 97 | int arr[SIZE]; 98 | 99 | for (int k = 0; k < SIZE; k++) { 100 | if (elemB->string[k] != '\0') { 101 | arr[k] = elemB->string[k] - 64; 102 | } else { 103 | arr[k] = 0; 104 | } 105 | } 106 | 107 | return v->operation(arr); 108 | } 109 | 110 | Visitor_t * newVisitor(int (*operation)(int *arr)) 111 | { 112 | Visitor_t *v = (Visitor_t *) malloc(sizeof(Visitor_t)); 113 | 114 | v->visitElementA = visitElementA; 115 | v->visitElementB = visitElementB; 116 | v->operation = operation; 117 | 118 | return v; 119 | } 120 | 121 | int countEmpty(int *arr) 122 | { 123 | int numEmpty = 0; 124 | 125 | for (int k = 0; k < SIZE; k++) { 126 | if (!arr[k]) { 127 | numEmpty++; 128 | } 129 | } 130 | 131 | return numEmpty; 132 | } 133 | 134 | int sum(int *arr) 135 | { 136 | int sum = 0; 137 | 138 | for (int k = 0; k < SIZE; k++) { 139 | sum += arr[k]; 140 | } 141 | 142 | return sum; 143 | } 144 | 145 | int display(int *arr) 146 | { 147 | for (int k = 0; k < SIZE; k++) { 148 | printf("%d ", arr[k]); 149 | } 150 | printf("\n"); 151 | } 152 | 153 | int main(void) 154 | { 155 | int a, b; 156 | 157 | ElementA_t *elemA = newElementA(); 158 | ElementB_t *elemB = newElementB(); 159 | 160 | Visitor_t *displayVisitor = newVisitor(display); 161 | Visitor_t *countEmptyVisitor = newVisitor(countEmpty); 162 | Visitor_t *sumVisitor = newVisitor(sum); 163 | 164 | printf("The integer contents of ElementA: "); 165 | elemA->accept(elemA, displayVisitor); 166 | printf("The integer contents of ElementB: "); 167 | elemB->accept(elemB, displayVisitor); 168 | 169 | a = elemA->accept(elemA, countEmptyVisitor); 170 | b = elemB->accept(elemB, countEmptyVisitor); 171 | 172 | printf("The number of \"0\" spots in ElementA is %d\n", a); 173 | printf("The number of \"0\" spots in ElementB is %d\n", b); 174 | 175 | a = elemA->accept(elemA, sumVisitor); 176 | b = elemB->accept(elemB, sumVisitor); 177 | 178 | printf("The sum of all elements in ElementA is %d\n", a); 179 | printf("The sum of all elements in ElementB is %d\n", b); 180 | 181 | return 0; 182 | } 183 | -------------------------------------------------------------------------------- /interpreter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Intent 7 | * - Given a language, define a representation for its grammar along with an 8 | * interpreter that uses the representation to interpret sentences in the 9 | * language. 10 | */ 11 | 12 | /** 13 | * Use the Interpreter pattern when there is a language to interpret, and you 14 | * can represent statements in the language as abstract syntax trees. The 15 | * interpreter pattern works best when 16 | * - The grammar is simple. For complex grammers, the class heirarchy for the 17 | * grammar becomes large and unmanageable. Tools such as parser generators are 18 | * a better alternative in such cases. They can interpret expressions without 19 | * building abstract syntax trees, which can save space and possibly time. 20 | * - Efficiency is not a critical concern. The most efficient interpreters are 21 | * usually *not* implemented by interpreting parse trees directly but by first 22 | * translating them into another form. For example, regular expressions are 23 | * often transformed into state machines. But even then, the *translator* can 24 | * be implemented by the Interpreter pattern, so the pattern is still 25 | * applicable. 26 | */ 27 | 28 | /* 29 | * The expression is an abstract class that declares an abstract Interpret 30 | * operation that is common to all nodes in the abstract syntax tree. 31 | */ 32 | 33 | /* 34 | * The concrete TerminalExpression class implements an Interpret operation 35 | * associated with terminal symbols in the grammar. 36 | */ 37 | typedef struct TerminalExpression_s TerminalExpression_t; 38 | 39 | /* 40 | * The concrete NonterminalExpression class implements an Interpret operation 41 | * for nonterminal symbols in the grammar. Interpret calls itself recursively 42 | * on the variables representing the rules (R1 .. Rn). 43 | * 44 | * One class of this is required for every rule R. 45 | */ 46 | typedef struct NonterminalExpression_s NonterminalExpression_t; 47 | 48 | /* 49 | * Contains information that is global to the interpreter 50 | */ 51 | typedef struct Context_s Context_t; 52 | 53 | /* 54 | * The AbstractSyntaxTree is usually built up from the client, which is 55 | * assembled by instances of TerminalExpression and NonterminalExpression. 56 | */ 57 | typedef struct AbstractSyntaxTree_s AbstractSyntaxTree_t; 58 | 59 | struct TerminalExpression_s { 60 | void (*interpret)(TerminalExpression_t *, Context_t *); 61 | }; 62 | 63 | struct NonterminalExpression_s { 64 | void (*interpret)(NonterminalExpression_t *, Context_t *); 65 | }; 66 | 67 | struct Context_s { 68 | bool upper; 69 | }; 70 | 71 | void teInterpret(TerminalExpression_t *te, Context_t *c) 72 | { 73 | if (c->upper) { 74 | printf("TERMINAL EXPRESSION\n"); 75 | } else { 76 | printf("terminal expression\n"); 77 | } 78 | } 79 | 80 | TerminalExpression_t *newTerminalExpression(void) 81 | { 82 | TerminalExpression_t *te 83 | = (TerminalExpression_t *) malloc(sizeof(TerminalExpression_t)); 84 | 85 | te->interpret = teInterpret; 86 | 87 | return te; 88 | } 89 | 90 | void nteInterpret(NonterminalExpression_t *nte, Context_t *c) 91 | { 92 | if (c->upper) { 93 | printf("NONTERMINAL EXPRESSION\n"); 94 | } else { 95 | printf("nonterminal expression\n"); 96 | } 97 | } 98 | 99 | NonterminalExpression_t *newNonterminalExpression(void) 100 | { 101 | NonterminalExpression_t *nte 102 | = (NonterminalExpression_t *) malloc(sizeof(NonterminalExpression_t)); 103 | 104 | nte->interpret = nteInterpret; 105 | 106 | return nte; 107 | } 108 | 109 | typedef enum { 110 | TERMINAL, 111 | NONTERMINAL, 112 | } Expression_t; 113 | 114 | #define MAX_EXPRESSIONS 4 115 | struct AbstractSyntaxTree_s { 116 | void *expression[MAX_EXPRESSIONS]; 117 | Expression_t type[MAX_EXPRESSIONS]; 118 | int numExpressions; 119 | 120 | void (*add)(AbstractSyntaxTree_t *abs, Expression_t type, void *e); 121 | }; 122 | 123 | void absAdd(AbstractSyntaxTree_t *abs, Expression_t type, void *te) 124 | { 125 | abs->expression[abs->numExpressions] = (void *) te; 126 | abs->type[abs->numExpressions] = type; 127 | 128 | abs->numExpressions++; 129 | } 130 | 131 | AbstractSyntaxTree_t *newAbstractSyntaxTree(void) 132 | { 133 | AbstractSyntaxTree_t *abs 134 | = (AbstractSyntaxTree_t *) malloc(sizeof(AbstractSyntaxTree_t)); 135 | 136 | abs->numExpressions = 0; 137 | 138 | abs->add = absAdd; 139 | 140 | return abs; 141 | } 142 | 143 | void interpret(Expression_t type, void *expression, Context_t *context) 144 | { 145 | TerminalExpression_t *te; 146 | NonterminalExpression_t *nte; 147 | 148 | switch (type) { 149 | case TERMINAL: 150 | te = (TerminalExpression_t *) expression; 151 | te->interpret(te, context); 152 | break; 153 | case NONTERMINAL: 154 | nte = (NonterminalExpression_t *) expression; 155 | nte->interpret(nte, context); 156 | break; 157 | } 158 | } 159 | 160 | int main(void) 161 | { 162 | /* Usually a tree, but for simplicity it behaves as a list */ 163 | AbstractSyntaxTree_t *abs = newAbstractSyntaxTree(); 164 | 165 | abs->add(abs, TERMINAL, (void *) newTerminalExpression()); 166 | abs->add(abs, NONTERMINAL, (void *) newNonterminalExpression()); 167 | abs->add(abs, TERMINAL, (void *) newTerminalExpression()); 168 | abs->add(abs, TERMINAL, (void *) newTerminalExpression()); 169 | 170 | printf("CONTEXT A\n"); 171 | Context_t contextA = { .upper = true }; 172 | for (int k = 0; k < abs->numExpressions; k++) { 173 | interpret(abs->type[k], abs->expression[k], &contextA); 174 | } 175 | 176 | printf("\ncontext b\n"); 177 | Context_t contextB = { .upper = false }; 178 | for (int k = 0; k < abs->numExpressions; k++) { 179 | interpret(abs->type[k], abs->expression[k], &contextB); 180 | } 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /composite.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Intent 6 | * - Compose objects into tree structures to represent part-whole heirarchies. 7 | * Composite lets clients treat individual objects and compositions of objects 8 | * uniformly. 9 | */ 10 | 11 | /** 12 | * Use the Composite pattern when 13 | * - you want to represent part-whole heirarchies of objects. 14 | * - you want clients to be able to ignore the difference between compositions 15 | * of objects and individual objects. Clients will treat all objects in the 16 | * composite structure uniformly. 17 | */ 18 | 19 | /* For this example, use a static array. Typically would use an iterator. */ 20 | #define MAX_CHILDREN 10 21 | 22 | static unsigned compositeId; 23 | 24 | /** 25 | * - defines behavior for components having children. 26 | * - stores child components. 27 | * - implements child-related operations in the Component interface. 28 | */ 29 | typedef struct Composite_s { 30 | void (*operation)(struct Composite_s *self); 31 | void (*operationAll)(struct Composite_s *self); 32 | void (*add)(struct Composite_s *self, struct Composite_s *c); 33 | void (*remove)(struct Composite_s *self, struct Composite_s *c); 34 | struct Composite_s * (*getChild)(struct Composite_s *self, int index); 35 | 36 | int id; 37 | char *type; 38 | 39 | struct Composite_s * child[MAX_CHILDREN]; 40 | } Composite_t; 41 | 42 | static void compositeOperation(Composite_t *this) 43 | { 44 | printf("%s %d: operation\n", this->type, this->id); 45 | } 46 | 47 | static void compositeOperationAll(Composite_t *this) 48 | { 49 | printf("%s %d: operationAll\n", this->type, this->id); 50 | for (int k = 0; k < MAX_CHILDREN; k++) { 51 | if (this->child[k] != NULL) { 52 | this->child[k]->operation(this->child[k]); 53 | if (this->child[k]->operationAll) { 54 | this->child[k]->operationAll(this->child[k]); 55 | } 56 | } 57 | } 58 | } 59 | 60 | static void compositeAdd(Composite_t *this, Composite_t *addComposite) 61 | { 62 | for (int k = 0; k < MAX_CHILDREN; k++) { 63 | if (this->child[k] == NULL) { 64 | printf("%s %d: add %s %d\n", this->type, this->id, addComposite->type, addComposite->id); 65 | this->child[k] = addComposite; 66 | break; 67 | } 68 | } 69 | } 70 | 71 | static void compositeRemove(Composite_t *this, Composite_t *removeComposite) 72 | { 73 | for (int k = 0; k < MAX_CHILDREN; k++) { 74 | if (this->child[k]->id == removeComposite->id) { 75 | printf("%s %d: remove %s %d\n", this->type, this->id, 76 | this->child[k]->type, this->child[k]->id); 77 | this->child[k] = NULL; 78 | break; 79 | } 80 | } 81 | } 82 | 83 | static Composite_t * compositeGetChild(Composite_t *this, int index) 84 | { 85 | if (this->child[index] == NULL) { 86 | printf("%s %d: no child at index %d\n", this->type, this->id, index); 87 | } else { 88 | printf("%s %d: get child at index %d (id = %d)\n", this->type, this->id, 89 | index, this->child[index]->id); 90 | } 91 | 92 | return this->child[index]; 93 | } 94 | 95 | Composite_t * newComposite(void) 96 | { 97 | Composite_t *composite = (Composite_t *) malloc(sizeof(Composite_t)); 98 | 99 | composite->operation = compositeOperation; 100 | composite->operationAll = compositeOperationAll; 101 | composite->add = compositeAdd; 102 | composite->remove = compositeRemove; 103 | composite->getChild = compositeGetChild; 104 | 105 | composite->id = compositeId++; 106 | composite->type = "composite"; 107 | 108 | return composite; 109 | } 110 | 111 | /** 112 | * - represents leaf objects in the composition. A leaf has no children. 113 | * - defines behavior for primitive objects in the composition. 114 | */ 115 | typedef Composite_t Leaf_t; 116 | 117 | Leaf_t * newLeaf(void) 118 | { 119 | Leaf_t *leaf = (Leaf_t *) malloc(sizeof(Leaf_t)); 120 | 121 | leaf->operation = compositeOperation;; 122 | leaf->operationAll = NULL; 123 | leaf->add = NULL; 124 | leaf->remove = NULL; 125 | leaf->getChild = NULL; 126 | 127 | leaf->id = compositeId++; 128 | leaf->type = "leaf"; 129 | 130 | return leaf; 131 | } 132 | 133 | /** 134 | * - declare the interface for objects in the composition 135 | * - implements default behavior for the interface common to all classes 136 | * - declares an interface for accessing and managing its child components 137 | */ 138 | typedef Composite_t component_t; 139 | 140 | /** 141 | * - manipulates objects in the composition through the component interface 142 | */ 143 | typedef struct client_s { 144 | component_t *component; 145 | } client_t; 146 | 147 | int main(void) 148 | { 149 | Composite_t *composite0 = newComposite(); 150 | Composite_t *composite1 = newComposite(); 151 | Composite_t *composite2 = newComposite(); 152 | 153 | Leaf_t *leaf3 = newLeaf(); 154 | Leaf_t *leaf4 = newLeaf(); 155 | Leaf_t *leaf5 = newLeaf(); 156 | 157 | composite0->operation(composite0); 158 | composite1->operation(composite1); 159 | composite2->operation(composite2); 160 | 161 | leaf3->operation(leaf3); 162 | leaf4->operation(leaf4); 163 | leaf5->operation(leaf5); 164 | 165 | composite0->add(composite0, leaf3); 166 | composite0->add(composite0, leaf4); 167 | 168 | composite0->remove(composite0, leaf3); 169 | composite0->add(composite0, leaf3); 170 | 171 | composite0->add(composite0, composite1); 172 | composite0->add(composite0, composite2); 173 | 174 | composite2->add(composite2, leaf5); 175 | 176 | Composite_t *tmp = composite0->getChild(composite0, 2); 177 | tmp->operation(tmp); 178 | 179 | composite0->operationAll(composite0); 180 | 181 | free(composite0); 182 | free(composite1); 183 | free(composite2); 184 | free(leaf3); 185 | free(leaf4); 186 | free(leaf5); 187 | 188 | return 0; 189 | } 190 | --------------------------------------------------------------------------------