Design Patterns: Exploring Embedded C Language Implementation – 14. Remote Proxy Pattern

Introduction:This article will briefly describe the remote proxy pattern from the book Head First Design Patterns and implement this pattern using C language.Background of Remote Proxy Pattern Implementation:

The background of the remote proxy pattern revolves around the remote monitoring of a candy machine.

The CEO of the candy company wants to better monitor the candy machines and obtain reports on inventory and machine status. Initially, the programmer designed an operator that could generate relevant reports locally, but the CEO further requested remote monitoring of the candy machines, allowing him to view the status of candy machines distributed in various locations from his office.

However, the original monitor and candy machines were executed on the same Java Virtual Machine (JVM), which belonged to local monitoring and could not meet the needs of remote monitoring. To solve this problem, the programmer decided to introduce the remote proxy pattern. The specific approach is to create a remote proxy object that has the same interface as the remote candy machine. The monitor only needs to operate the local proxy object, which is responsible for communicating with the remote real candy machine over the network, forwarding the monitor’s requests to the remote candy machine, and returning the responses from the remote candy machine to the monitor. Thus, for the monitor, it is as if it is directly operating the remote candy machine without worrying about the underlying details of network communication.

Design Patterns: Exploring Embedded C Language Implementation - 14. Remote Proxy PatternPattern Definition:The remote proxy acts as a representative of a local object, controlling access to a real object located in a different address space (usually a remote network node). It encapsulates the details of network communication, allowing the client to interact with the remote object as if it were a local object, without worrying about the complexities of network transmission, address resolution, data serialization, etc.Component Diagram:Based on the background story and pattern definition, we can draw the component class diagram for this example. From the diagram, we can see that the real candy machine CandyMachine and the CandyMachineProxy proxy both use the same candy machine interface CandyMachineInterface.Design Patterns: Exploring Embedded C Language Implementation - 14. Remote Proxy PatternCore Data Structures and Code Snippets:Here we only provide the core data structures and code snippets. The complete code can be found in the GitHub repository at the end of this article.

  • Definition of Candy Machine State Enumeration:
typedef enum{  SOLD_OUT,  NO_QUARTER,  HAS_QUARTER,  SOLD  }State;
  • Definition of Candy Machine Interface (Function Pointers):
typedef struct {  State (*getState)(void* machine);  int (*getCount)(void* machine);  const char* (*getLocation)(void* machine); }CandyMachineInterface;
  • Real Candy Machine (Remote Object):
struct CandyMachine {  CandyMachineInterface* vtable;  int count;  State state;  char location[20];};
  • Proxy Object (Local Proxy):
struct CandyMachineProxy {   CandyMachineInterface* vtable;   // The proxy needs to know the location of the remote object   char location[20];  };
  • Proxy Method getState:
State proxyGetState(void* machine){  CandyMachineProxy *proxy = (CandyMachineProxy*)machine;  // Send request to remote  sendOverNetwork("REQUEST_STATE");  // Receive response  char response[20];  receiveFromNetwork(response,sizeof(response));  // Convert response to state  if(strcmp(response,"SOLD_OUT") == 0) return SOLD_OUT;  ...  ...  return SOLD_OUT; }
  • Proxy Method getCount:
int proxyGetCount(void* machine) {CandyMachineProxy* proxy=(CandyMachineProxy*)machine;// Send request to remote sendOverNetwork("REQUEST_COUNT");// Receive response char response[20]; receiveFromNetwork(response,sizeof(response));// Convert response string to count return atoi(response);}
  • Proxy Method getLocation:
const char* proxyGetLocation(void* machine){  CandyMachineProxy* proxy = (CandyMachineProxy*)machine;  return proxy->location;  }
  • Proxy Interface Table:
CandyMachineInterface proxyVtable = {    proxyGetState,    proxyGetCount,    proxyGetLocation  };
  • Client Code – Monitor:
void monitorMachine(CandyMachineInterface* machine, void* instance){    printf("\nMonitoring Candy Machine: %s\n", machine->getLocation(instance));    printf("Current Inventory: %d\n", machine->getCount(instance));    State state = machine->getState(instance);    printf("Current Status: ");    switch (state) {      case SOLD_OUT: printf("Sold Out\n"); break;      case NO_QUARTER: printf("No Quarter\n"); break;      case HAS_QUARTER: printf("Has Quarter\n"); break;      case SOLD: printf("Selling\n"); break;      }    }
  • Test Code:
int main() {  // Initialize candy machine and proxy  initMachine("Central Station",10);  // Client monitors remote candy machine through proxy  printf("=== First Monitoring ===\n");  monitorMachine(proxy.vtable, &proxy);  // Simulate remote operation  simulateRemoteOperation();  // Monitor again  printf("\n=== Second Monitoring ===\n");  monitorMachine(proxy.vtable, &proxy);  return 0;  }
  • Running Result:

Design Patterns: Exploring Embedded C Language Implementation - 14. Remote Proxy PatternThe Application of Remote Proxy Pattern in Embedded Field:The remote proxy pattern has a wide range of applications in embedded systems, especially in distributed embedded systems and multi-node collaboration scenarios. Its core value lies inhiding the communication details of remote devices (such as network protocols and hardware interface differences), allowing local nodes to access remote resources as if they were local objects, while optimizing resource utilization and improving system reliability. For example:

  • Communication between sensors and controllers in Industrial Internet of Things (IIoT):In factories, embedded devices such as temperature sensors and pressure sensors may be distributed in different locations in the workshop, while the central controller (such as PLC) needs to obtain data from these sensors in real-time. At this time, a “sensor remote proxy” can be implemented on the controller side.

  • Debugging and upgrading embedded devices often require operations across physical locations (such as weather stations and base station equipment deployed in the field), and remote proxies can safely forward debugging commands and firmware data.

Conclusion:This article elaborated on the concept of the remote pattern and simulated monitoring the status of a remote candy machine using C language.It achieved transparency in accessing objects across address spaces, decoupling client code from remote objects, facilitating future expansions (such as changing communication protocols, adding permission verification, etc., only requiring modifications to the proxy without affecting the client).Code Repository:

https://github.com/MicroDevLog/DesignPatternInC

References:

[1]. “Head First Design Patterns” China Electric Power Press.

[2]. “Pattern-Oriented Software Architecture: Patterns for Distributed Systems” Volume I

Previous Issues:Design Patterns: Exploring Embedded C Language Implementation – 0. IntroductionDesign Patterns: Exploring Embedded C Language Implementation – 1. Strategy PatternDesign Patterns: Exploring Embedded C Language Implementation – 2. Observer PatternDesign Patterns: Exploring Embedded C Language Implementation – 3. Decorator PatternDesign Patterns: Exploring Embedded C Language Implementation – 4. Simple Factory PatternDesign Patterns: Exploring Embedded C Language Implementation – 5. Factory Method PatternDesign Patterns: Exploring Embedded C Language Implementation – 6. Abstract Factory PatternDesign Patterns: Exploring Embedded C Language Implementation – 7. Singleton PatternDesign Patterns: Exploring Embedded C Language Implementation – 8. Command PatternDesign Patterns: Exploring Embedded C Language Implementation – 9. Adapter PatternDesign Patterns: Exploring Embedded C Language Implementation – 10. Template Method PatternDesign Patterns: Exploring Embedded C Language Implementation – 11. Iterator PatternDesign Patterns: Exploring Embedded C Language Implementation – 12. Composite PatternDesign Patterns: Exploring Embedded C Language Implementation – 13. State PatternClick the following business card to follow this public account: If you like it, remember to “share” and “recommend” or “like” or “comment“.

Leave a Comment