Wrapper Facade: Structure mode for encapsulation functions in the class

zhaozj2021-02-16  57

Wrapper Facade: Type mode for package functions in the class Douglas C. Schmidt

1 Describe this paper describes the packaging model. The intent of this mode is to encapsulate low-level functions and data structures by the object-oriented (OO) interface. Examples of common packaging appearance mode are class libraries such as MFC, ACE, and AWT, which encapsulates local OS C APIs, such as Socket, PThreads, or GUI functions. Program directly for local OS C APIs makes network applications, unrestful, unmistable, and difficult to maintain, because application developers need to know many low-level, error-free details. This paper explains how packaging appearance mode makes these types of applications more simple, robust, portable, and maintenance. This thesis is organized as follows: 2 Detailed description Use the package appearance mode of Siemens format [1], 3 gives an end language. 2 Packaging Exterior Mode 2.1 intends to encapsulate low-level functions and data structures in a more concise, robust, portable and maintainable higher-level object-oriented interface interface. 2.2 Examples To explain the package appearance mode, consider the server of the distributed log service shown in Figure 2-1. The client application uses the log service to record information about their execution status in the distributed environment. These status information typically include error notifications, debugging tracking, and performance diagnostics. The logging is sent to the central log server, which is written to various output devices, such as the network management console, printer, or database.

Figure 1 Distributed Log Service

The log server shown in Figure 1 handles the connection request and log record sent by the customer. Logging and connection requests can be reached on multiple Socket handles. Each handle identifies network communication resources managed in the OS. Customer uses a connection protocol like TCP [2] to communicate with the log server. Thus, when the customer wants to log data, it must first send a connection request to the log server. The server uses the handle factory to accept the connection request, and the handle factory listens on the network address known by the customer. When the connection request arrives, the OS handle factory accepts the client's connection and creates the Socket handle indicating the connection endpoint of the client. The handle is returned to the log server, the latter waits for the client log request on this handle and other handles. Once the customer is connected, they can send logs to the server. The server receives these records, processes records, and writes them to their output devices through a connected Socket handle. The common way to develop concurrent log servers for multiple customers is to use low C language functions and data structures to complete operations such as thread, synchronization, and network communication. For example, Figure 2 demonstrates how to use Solaris Threads [3] and Socket [4] Network Programming API to develop multi-threaded log servers.

Figure 2 Multi-threaded log server

In this design, the handle factory of the log server accepts the customer network connection in its main thread. It is then derived a new thread and runs the logging_handler function in a separate connection to handle logging from each customer. The following two C functions demonstrate how to use the local Solaris OS API of Socket, muters, and threads to implement this log server design.

// At file scope.// Keep track of number of logging requests.static int request_count; // Lock to protect request_count.static mutex_t lock; // Forward declaration.static void * logging_handler (void *); // Port number to listen on for requests.static const int logging_port = 10000;. // main driver function for the multi-threaded // logging server Some error handling has been // omitted to save space in the example.int main (int argc, char * argv []) {struct sockaddr_in sock_addr;. // Handle UNIX / Win32 portability differences # if defined (_WINSOCKAPI_) SOCKET acceptor; #elseint acceptor; #endif / * _WINSOCKAPI_ * / // Create a local endpoint of communication.acceptor = socket (PF_INET, SOCK_STREAM, 0); // Set up the address to become a server.memset (reinterpret_cast (& sock_addr), 0, sizeof sock_addr); sock_addr.sin_family = AF_INET; sock_addr.sin_port = htons (logging_port) Sock_addr.sin_addr.s_addr = HTONL (INADDR_Any); // Associate Address with endpoint.bind (Acceptor, Reinterpret_cast (& sock_addr), sizeof sock_addr); // Make endpoint listen for connections.listen (acceptor, 5); // Main server event loop.for (;;) {thread_t t_id; // Handle UNIX / Win32 portability Differences. # ielseint h; #elseint h; #ENDIF / * _WINSOCKAPI_ * / // block waiting for clients to connection connect.int h = accept (acceptor, 0, 0); // spawn a new thread That runs the // entry point and // processes client logging records on // socket handle .thr_create (0, 0, logging_handler, reinterpret_cast (h), THR_DETACHED, & t_id);} / * NOTREACHED * / RETURN 0;} logging_handler function runs in separate thread control, that is, each customer a thread.

It receives and processs logging on each connection, as shown below: // entry points processes logging records for // one client connection.void * logging_handler (void * arg) {// handle unix / win32 portability Differences. # IF Defined (_winsockapi_) socket h = reinterpret_cast (arg); # elseint h = reinterpret_cast (arg); # endif / * _winsockapi_ * / for (;;) {uint_32 len; // ENSURE A 32-bit Quantity.char log_record [log_record_max]; // the first reads the length // (Stored As a 32-bit integer) of // adjacent logging record. this code // does not handle "short- s ".ssize_t n = recv (h, reinterpret_cast (& len), sizeof len, 0); // bail out if we don't get the expected len.if (n <= sizeof len) Break; len = NTOHL (LEN); // Convert Byte-Order.if (LEN> Log_Record_max) Break; // The Second The Reads // Bytes To Obtain The Actual Record.// This Code Handles "Short - < Recv> s ".for (size_t nread = 0; NREAD

Generally speaking, the code to write and maintain is very boring, often contains subtle and harmful errors. For example, the code created and initialized in the main function of 2.2 is easy to erroneously erroneously erroneous, such as clearing the SOCK_ADDR, or does not use Htons [5] for the Logging_Port number. Mutex_lock and mutex_unlock are also easily misused. For example, if the Write call returns -1, the logging_handler code will not release the mutex lock and jump out of the loop. Similarly, if the nesting for loop is returned when an error is encountered, the Socket handle h will not be turned off. Lack of portability: Software written using low-level functions and data structures can often be transplanted between different OS platforms and compilers. Moreover, they often do not transplant in different versions of the same OS or compiler. Unavailability stems from hidden information in a function of low-level API and data structures. For example, the log server in 2.2 has hardly encoded the dependence on several non-portable local OS threads and network programming C APIs. In particular, the use of THR_CREATE, MUTEX_LOCK and MUTEX_UTEX_LOCK and MUTEX_UNLOCK cannot be ported to the non-Solaris OS platform. Similarly, specific Socket features, such as using Int represents the Socket handle, cannot be ported to non-Unix platforms like Win32 WINSOCK; Winsock represents the Socket handle as a pointer. High maintenance overhead: C and C developers are usually obtained by explicitly increase the conditional compilation instructions in their application source code using #ifdef. However, the use of conditional compilation to handle platform-specific variants increase the physical design complexity of application source code [6]. Developers are difficult to maintain and extend such software because the platform unique implementation details are dispersed in all parts of the application source file. For example, WIN32 and UNIX portability of the Socket data type (that is, socket vs. int) hinder the readability of the code. Developers who make programming such as low-level C APIs must be familiar with many OS platform features to write and maintain the code. Due to these disadvantages, it is often not a valid design choice by programming the low-level functions and data structures. 2.5 Solution To ensure that an effective way to access low-level functions and data structures is to use packaging appearance mode. For each set of related functions and data structures, one or more packaging appearance classes are created, and the low-level functions and data structures are encapsulated in the packaging appearance interface. 2.6 Structure of Participants in Structure Packaging Models Demo in the following UML class diagram: Key Participants in the packaging model include: Function: Function is an existing low-level function and data structure, which provides consolidation Cohesive service. Packaging appearance (Wrapper Fa? ADE): The appearance of the packaging is a package function and one or a set of classes of the data structure associated therewith. The method provided by the packaging is forwarded to one or more lower functions. 2.7 Dynamic Characteristics The following figure shows various collaboration in the packaging appearance mode:

As mentioned below, these collaboration is very simple: 1. CLIENT INVOCATION: Customer calls the method through the instance of the packaging appearance. 2. Forwarding: The packaging look forward to forward the request to the one or more underlying functions of it package, and transfer any internal data structure required for the function. 2.8 Implementation This section explains the steps involved in the components and applications through the packaging appearance mode. We will explain how these packaging appearances have overcome the cumbersome, unachable procedures, lack of portability, and high maintenance overhead; these problems have torture solutions using low-level functions and data structures. The examples described herein are based on the log servers described in 2.2, and Figures 2-3 demonstrate the structure and participants in this example. The example in this section applies a reusable component from the ACE framework [7]. ACE provides a rich set of rich C packaging and framework components to complete common communication software tasks across extensive OS platforms. Figure 3 Multi-threaded log servers

The following steps can be taken to implement packaging model: 1. Determine the abstraction and relationship between existing functions: a traditional API that is implemented as a stand-alone function and data structure like Win32, POSIX or X Windows. Abstract, such as network programming, synchronization, and threads, and GUI management mechanisms. However, due to lack of data abstract support in low-level languages ​​like C, developers often do not immediately understand how these existing functions and data structures are associated with each other. Therefore, the first step in applying the packaging appearance is to determine the abstraction and relationship between the lower level functions in the existing API. In other words, we define an "object model" by aggregating existing low-level API functions and data structures into one or more classes. In our log case, we started a carefully checking our original log server. This implementation uses many low-level functions, which are actually provided with several consolidated services, such as synchronous and network communication. For example, Mutex_lock and Mutex_unlock functions are associated with mutex synchronization abstraction. Similarly, Socket, Bind, Listen and Accept functions play a variety of roles of network programming abstraction. 2. Polymerize the inner function group into the package appearance class and method: This step can be divided into the following sub-step: In this step, we define one or more packages for each set of compact abstraction functions and data structures. Appearance. A. Create a category: We start from each set of confineable functions and data structures to define one or more packaging appearances. Several common standards for creating categories of consolidation include: • Merging a function of high cohesion (cohesion) into an independent class while minimizing unnecessary coupling between the class. • Determine what is generic in the underlying function is a variable and puts the function packet into class, thereby isolating the change in a unified interface. In general, if the original API contains a wide variety of related functions, it is possible to create several packaging appearances to properly divide the transaction. B. Multiple independent functions are incorporated in: In addition to the existing function packet into classes, it is often beneficial in the method of less in combination in each package class. For example, to ensure that a set of low-level functions is called in an appropriate order, this design may be used. C. Select an indirect level: Most packaging appearances simply call their method to directly forward the low-level functions of the underlying. If the package appearance method is inline, there may be no additional indirect hierarchy compared to directly calling low-level functions. In order to enhance scalability, it is also possible to increase additional indirect hierarchy by dynamically assigning packaging appearance methods. In this case, the fabrication of the abstract (Abstract) role in the bridge mode [8] is placed. D. Determine where to deal with platform-specific variants: Make the platform-specific application code to minimize the importance of using packaging appearance mode. Thus, although the implementation of the packaging appearance method can be different on different OS platforms, they should provide a unified, platform-independent interface. A strategy for processing platform unique variants is to use #ifdef in the implementation of the packaging appearance method. When using #ifdef and automatic configuration tools (such as GNU AutoConf), you can create a unified, not dependent on the platform's packaging appearance. Another optional policy is to decompose different packaging appearances in a directory (for example, there is a directory for each platform), and configure language processing tools to include appropriate packaging appearance classes when compiling. in. Choosing a specific policy depends to a large extent on the frequency of change in the package appearance method. For example, if they frequently change, the #ifdef can be properly updated for each platform may be monotonous. Similarly, all files that depend on the file may need to be recompiled, even if there is a change only for one platform.

In our log example, we will define packaging appearances for muters, sockets, and threads to demonstrate how each step is implemented. As shown below: · Mutex packaging: We first define thread_mutex abstraction, package Solaris mutex function in unified and portable class interface: Class thread_mutex {public: thread_mutex (void) {mutex_init (& Mutex_, 0, 0 ?);} Thread_Mutex (void) {mutex_destroy (& mutex_);} int acquire (void) {return mutex_lock (& ​​mutex_);} int release (void) {return mutex_unlock (& ​​mutex_);} private: // Solaris-specific Mutex mechanism .mutex_t mutex_; // = Disallow copying and assignment.Thread_Mutex (const Thread_Mutex &); void operator = (const Thread_Mutex &);}; by defining the Thread Mutex class interface, and subsequently written to use it, rather than lower the local OS C API Applications, we can easily transplant our packaging to other platforms. For example, following the Thread Mutex implemented work on Win32: class Thread_Mutex {public:? Thread_Mutex (void) {InitializeCriticalSection (& mutex_);} Thread_Mutex (void) {DeleteCriticalSection (& mutex_);} int acquire (void) {EnterCriticalSection (& mutex_); return 0;} int release (void) {LeaveCriticalSection (& mutex_); return 0;} private: // Win32-specific Mutex mechanism.CRITICAL_SECTION mutex_; // = Disallow copying and assignment.Thread_Mutex (const Thread_Mutex &); void operator = (const thread_mutex &);}; If we described earlier, we can use a single source tree to provide a single source tree by using #ifdef and automatic configuration tools (such as Gun AutoConf) in the Thread_Mutex method implementation. The platform-independent mutex abstract. Instead, we can also achieve different THREAD_MUTEX to break down into the separated directory, and indicate that our language processing tool contains appropriate versions to enter our app when compiling. In addition to improving portability, our Thread_Mutex packaging appearance also provides a mutex interface than the direct programming low Solaris function and Mutex_t data structure is more inclusive. For example, we can use the C Private access control indicator to disable the copy and assignment of the mutex; such use is wrong, but it will not be blocked by less than a strong type C program API. · Socket packaging appearance: Socket API is much larger than Solaris mutex API, and there is also a lot of performance [5]. Therefore, we must define a set of related packaging appearances to encapsulate the socket.

We will start from the Typedef that the following processing UNIX / WIN32 portability: #if! Defined (_winsockapi_) typef int design; #define invalid_handle_value -1 # endif / * _winsockapi_ * / Next, we will define the inet_addr class, Package Internet Domain Address Structure: Class INET_ADDR {public: inet_addr (u_short port, long addr) {// set up the address to become a server.memset (reinterpret_cast (& addr_), 0, sizeof addr _); addr_. sin_family = AF_INET; addr_.sin_port = htons (port); addr_.sin_addr.s_addr = htonl (addr);} u_short get_port (void) const {return addr_.sin_port;} long get_ip_addr (void) const {return addr_.sin_addr. s_addr;} sockaddr * addr (void) const {return reinterpret_cast (& addr_);} size_t size (void) const {return sizeof (addr _);} // ... private: sockaddr_in addr_;}; Note INET_Addr How is the constructor cleared the SockAddr_in domain and make sure the port and IP addresses are converted to network word sequencing, eliminate several common socket programming errors. Next packaging appearance, SOCK_STREAM, encapsulate the I / O operation (such as RECV and SEND) that can be called on the connected socket handle: Class Sock_Stream {public: // = constructors.// default constructor.sock_stream (Void) ): handle_ (INVALID_HANDLE_VALUE) {} // Initialize from an existing HANDLE.SOCK_Stream (SOCKET h): handle_ (h) {} // Automatically close the handle on destruction.?SOCK_Stream (void) {close (handle_);} void SET_HANDE (SOCKET H) {Handle_ = H;} Socket get_handle_;} // = I / O Operations.int Recv (Char * BUF, SIZE_T LEN, INT FLAGS = 0); int send (const) Char * buf, size_t len, int flags = 0); // ... private: // handle for Exchanging socket data.socket handle_;}; Note how to ensure that the Socket handle is automatically in the SOCK_STREAM object closed. The SOCK_STREAM object is created by the connection factory SOCK_ACCEPTOR, the latter package passive connection establishment logic [9]. The SOCK_ACCEPTOR constructor initializes the passive mode receptacket to listen on the SOCK_ADDR address.

Likewise, accept the new factory methods accepted connections initialized SOCK_Stream, as follows: class SOCK_Acceptor {public: SOCK_Acceptor (const INET_Addr & sock_addr) {// Create a local endpoint of communication.handle_ = socket (PF_INET, SOCK_STREAM, 0) ; // Associate Address with endpoint.bind (Handle_, Sock_addr.addr (), SOCK_ADDR.SIZE ()); // Make Endpoint Listen for Connections.Listen (Handle_, 5);}; // Accept A connection and initialize / / The .int Accept (SOCK_STREAM & Stream) {stream.set_handle (Accept (Handle_, 0, 0)); if (stream.get_handle () == Invalid_Handle_Value) Return -1; else return 0;} private: / / Socket handle factory.socket handle_;}; Note How to ensure that the low-level socket, bind, and listen functions are always called in the correct order. Complete Socket packaging set also includes SOCK_CONNECTOR, encapsulated active connection establishment logic [9]. · Thread appearance: There are many thread APIs available on different OS platforms, including Solaris threads, POSIX PTHREADS, and WIN32 threads. These APIs show subtle syntax and semantic differences, for example, Solaris and POSIX threads can be "separated" mode is derived, while Win32 threads will not work. However, it can be provided with Thread_manager packaging appearance, and package these differences in a unified API. As follows: class Thread_Manager {public: int spawn (void * (* entry_point) (void *), void * arg, long flags, long stack_size = 0, void * stack_pointer = 0, thread_t * t_id = 0) {thread_t t ; if (t_id == 0) T_ID = & t; returntr_create (stack_size, stack_point, entry_point, arg, flags, t_id);} // ...}; thread_manager also provides a join and cancellation thread. 1. Determine the error handling mechanism: The low-level C function API usually uses the return value and integer code (such as errno) to notify them to them. However, this technology is easily error-free because the caller may forget the return status of their function calls. A more elegant report is wrong to use exception handling. Many programming languages, such as C and Java, use exception handling as an error reporting mechanism. It is also used by some operating systems, such as Win32. There are several benefits of using an exception handle as a packaging appearance class: • It is scalable: Modern programming language allows extending exception handling policies and mechanisms by having a small feature of existing interfaces and using extreme interference. For example, C and Java use inheritance to define hierarchical levels.

· It makes the error handle to cleanly decouple the error: For example, the error handling information does not explicitly pass to the operation. Moreover, the application does not ignore the exception because there is no check function to return values. · It can be type secure: In languages ​​like C and Java, it is thrown out and captured in a strongly type, to enhance the organization and correctness of the error handling code. The compiler will ensure the correct processor for each type of exception is performed relative to the explicitly checking the thread. However, there are several disadvantages for the use of abnormalities for packaging appearance: • It is not common: not all languages ​​provide exception handling. For example, some C compilers do not have an exception. Similarly, when the OS provides an abnormal service, they must be supported by the language extension, thereby reducing the transplantability of the code. · It makes it complicated in multiple languages: Instead, use an integer or structure to report error messages to provide a more common solution. · It makes resource management complicates: If there are multiple exit paths in the C or Java code block, resource management may become complex [10]. Thus, if language or programming environments do not support garbage collection, you must take care of ensuring that the dynamically assigned object is removed when there is abnormally thrown out. · It has potential time and / or space inefficient possibility: Even if there is no abnormality thrown out, the bad implementation of abnormal processing will also bring overhead overhead of time and / or space [10]. Such overhead may be particularly problematic for embedded systems that must have efficient and low memory occupancy characteristics. The disadvantage of abnormal processing is also particularly problematic for packaging appearances for encapsulated internal nuclear-level device drivers or low-level OS APIs (they must be ported to many platforms). For these types of packaging appearance, more portable, efficient, and thread safety processing errors are information that define an error processor abstraction, explicitly maintains success or failure of operations. Use thread-specific storage (Thread-Specific Storage) mode [11] is a solution that is widely used for these system-level packaging appearances. 1. Define the associated assistant class (optional): Once the low-level function and the data structure are encapsulated in the widget, it is often possible to create other helper classes to further simplify application development. These assistants have become significant after the package appearance mode has been applied to the category of the low-level function and the data associated with it. For example, in our log example, we can effectively utilize the KUARD class that implements C ScopeD Locking idios; this idiom ensures that thread_mutex is properly released, regardless of how the program's control flow exits the action. Template Class Guard {public: Guard (LOCK & LOCK): LOCK_ (LOCK) {Lock_.acquire ();}? Guard (void) {lock_.release ();} private: // Hold The Lock by Reference To avoid // the use of the copy constructor ... lock & lock_;} Guard class Apply the C idiom described in [12], thereby, "constructor acquires resources in a certain field" "constructor to get resources ".

As shown below: // ... {// Constructor of AutomaticLy // acquires the lock.guard MON (MUTEX); // ... Operations That Must Be Serialized ... / / Destructor of Automatically // Releases The Lock.} // ... Because we use a class like Thread_Mutex packaging appearance, we can easily replace different types of lock mechanisms, which is still Using the automatic lock / unlock protocol of Guard. For example, we can replace the Thread_mutex class with the Process_Mutex class, as shown below: // acquire a process-wide ituteX.guard MON (MUTEX); if you use C function and data structure, not a C class, get this The degree "pluggability" is more difficult. 2.9 Example Solution The following code demo log server's main function, which has been overridden with the plug-in appearance of the mutex, socket, and threads described in 2.8. // At file scope.// Keep track of number of logging requests.static int request_count; // Manage threads in this process.static Thread_Manager thr_mgr; // Lock to protect request_count.static Thread_Mutex lock; // Forward declaration.static void * logging_handler (void *); // Port number to listen on for requests.static const int logging_port = 10000;. // Main driver function for the multi-threaded // logging server Some error handling has been // omitted to save space in the example.int main (int argc, char * argv []) {// Internet address of server.INET_Addr addr (port); // Passive-mode acceptor object.SOCK_Acceptor server (addr); SOCK_Stream new_stream; // Wait For a connection from aclient.for (;;) {// accept a connection from a client.server.accept (new_stream); // get the underlying handle.socket h = new_stream.get_handle (); // spawn offn off A Thread-per-connection.thr_mgr.spaw (logging_handler, reinterpret_cast (h), thr_detached);}} logging_handler function runs in separate thread control, that is, each connected customer has a thread.

It receives and processs logging on each connection, as shown below: // entry point what processes logging records for // one client connection.void * logging_handler (void * arg) {socket h = reinterpret_cast (arg); // Create a Object from socket .sock_stream stream (h); for (;;) {uint_32 gen; // ENSURE A 32-bit quantity.char log_record [log_record_max]; // THE FIRST Reads the length // (Stored As a 32-bit Integer) of // adjacent logging record. this code // handles "Short- S" .ssize_t n = stream.recv_n (ReinterPret_cast (& len) ), sizeof le); // bail out if we're shutdown or // error (n <= 0) Break; len = ntohl (len); // convert Byte-Ordering.if (LEN> log_record_max Break; // the second Then Reads // bytes to Obtain the Actual Record.// this code handles "Short- S" .n = stream.recv_n (log_record, len); / / Bail out if we're shutdown or // error (n <= 0) Break; {// constructor of guard automatic or // acquires the lock.guard mon (lock); // Execute following two statements in a // critical section to avoid race conditions // and scrambled output, respectively request_count;. // Count # of requests if (write (STDOUT, log_record, len ) == -1) Break; // destructor of guard automaticly // Releases The Lock, Regardless Of // How We exit this block!}} // deStructor of AutomaticLy // Closes Down .Return 0 } Note how the above code solutions to the various problems of the code shown in 2.2. For example, the destructure of SOCK_STREAM and Guard closes the Socket handle and releases Thread_Mutex, regardless of how the code block exits. Similarly, this code is much easier to transplant and maintain because it does not use the platform unique API.

2.10 It is known to apply the example in this paper to focus on concurrent network programming. However, the packaging model has been applied to many other areas, such as the GUI framework and database class library. Below is some widely known applications of packaging appearance mode: Microsoft Foundation Class (MFC): MFC provides a set of packaging appearances of a set of packages, mainly focusing on providing a GUI component that implements Microsoft document / template architecture. ACE Frame: 2.8 Described muters, threads and socket packages are based on components in the ACE framework, respectively [7]: ACE_THREAD_MUTEX, ACE_THREAD_MANAGER, and ACE_SOCK * class. Rogue Wave Category Library: Rogue Wave Net.h and Threads.h Class libraries implements the packaging appearance of Socket, threads, and synchronization mechanisms on many OS platforms. Objectspace System : The toolkit also provides a packaging appearance of the socket, threads, and synchronization mechanisms. Java Virtual Machines and Java Basic Category Library: Java Virtual Machines (JVM) and various Java base class libraries, such as AWT and SWING, providing a set of low-level local OS system calls and GUI API packaging appearances. 2.1 Effects The following benefits provide the following benefits: more concise and robust programming interface: Packaging appearance mode packages many low-level functions in a more concise OO method. This reduces the boring properties of using low-level functions and data structures, thereby reducing the potential of programming errors. Improve application portability and maintainability: The implementation of packaging appearances can be used to shield the application developers with low-level functions and non-portable aspects of the data structure. Moreover, by replacing a physical design entity (such as file and #ifdef) based policy [6], the package appearance mode improves the software structure based on the policy of the physical design entity (such as the base class, subclass, and the relationship) of a logic design entity (such as base class, subclass, and their relationship) [6]. . In general, it is easier to understand and maintain according to the logical design of the application, rather than physical design. Improve the modular, reusability, and configurability of the application: By using OO language features such as inheritance and parameterization type, the reusable class component created by the packaging appearance mode can be "inserted" other components as a whole. Or "unplug" from it. Conversely, do not help with coarse granular OS tools, such as linkers or file systems, replacing components of groups. The packaging appearance mode has the following disadvantages: an additional indirectness: The packaging appearance mode may bring additional indirect compared to the data structure directly using the low-level functions. However, support inline language, such as C , can implement this mode without significant overhead, because the compiler can be built to implement a method of implementing a packaging appearance.

2.12 See the exterior mode and appearance mode is similar [8]. The intent of the appearance mode is to simplify the interface of the subsystem. The intent of the packaging model is more specific: it provides simple, robust, portable and maintainable type interface, low-level functions and data structures, such as local OS muters, sockets, threads, and GUI C language APIs. In general, the appearance hides complex class relationships behind the simpler API, while the packaging appearance hides complex functions and data structure relationships behind the richest class API. If dynamic assignments are used to implement packaging appearance methods, packaging appearance mode can be implemented using bridge mode [8]; packaging appearance method plays an abstraction role in bridge mode. 3 Conclusion This paper describes the packaging model and gives a detailed example demonstration how to use it. The implementation of the ACE packaging appearance assembly described in this paper can be freely acquired in the ACE [7] software release (URL: http://www.cs.wustl.edu/~ Schmidt/ace.html). This release contains a complete C source code, documentation, and test example driver developed in the University of St. Louis Washington. At present, ACE is using many companies (like Bellcore, Boeing, Dec, Ericsson, Kodak, Lucent, Motorola, SAIC and Siemens) communication software projects. Thank you for thanks to Hans Rohnert, Regine Meunier, Michael Stal, Christa Schwanninger, Frank Buschmann and Brad Applet, which greatly improves the form and content of packaging appearance mode description.

Reference [1] F. Buschmann, R. Meunier, H. Rohnert, P. Sommerlad, And M. Stal, Pattern-Oriented Software Architecture - a System of patterns. Wiley and Sons, 1996. [2] Wrstevens, UNIX NetWork Programming, First et Edition. Englewood Cliffs, NJ: Prentice Hall, 1990. [3] J. Eykholt, S. Kleiman, S. Barton, R. Faulkner, A. ShiValin-Giah, M. Smith, D. Stein, J Volliams, "Beyond Multiprocessing ... Multithreading The Sunos Ker-Nel," in Proceedings of The Summer Usenix Conference, (San Antonio, Texas), June 1992. [4] Wrstevens, UNIX Network Programming, Second Edition Englewood Cliffs, NJ:. Prentice Hall, 1997. [5] DC Schmidt, "IPC SAP: An Object-Oriented Interface to Interprocess Communication Services," C Report, vol.4, November / December 1992. [6] J. Lakos, Large-scale Software Development with C Reading, MA:. Addison-Wesley, 1995. [7] DC Schmidt, "ACE: an Object-Oriented Framework for Developing Distributed Applications," in Proceedings of the 6th Usenix C Technical Con Ference, (Cambridge, Mas-Sachusetts, Usenix Association, April 1994. [8] E. Gamma, R. Helm, R. Johnson, And J. Vlissides, Design Pat-Terns: Elements of Reusable Object-Oriented Software. Read -ing, MA: Addison-Wesley, 1995. [9] DC Schmidt, "Acceptor and Connector: Design Patterns for Initializing Communication Services," in Pattern Languages ​​of Program "(R. Martin, F. Buschmann, And D. Riehle, EDS.), Reading, MA: Addison-Wesley, 1997. [10] H. Mueller, "Patterns for Handling Exception Handling Suc-CessFully," C Report, Vol. 8, Jan. 1996. [11] DC Schmidt, T Harrison, "Thread-Specific Storage - An Object Behavioral Pattern for Accessing Per-Thread State EfficIntly," C

转载请注明原文地址:https://www.9cbs.com/read-24137.html

New Post(0)