How Layers Should Be Realized
The matter of how layers should be realized is determined by the client-server nature of the relationship between an application and its platform/virtual machine. This includes some characteristics of layers discussed previously:
-
Asymmetry:
- Interactions between a virtual machine and its application layer should be initiated exclusively by action of the application.
- (Note, however, that this applies only to steady-state operation, since there may be cases during system start up, shut down, or failure recovery, where the virtual machine may need to initiate the action.)
-
Interface-based interactions:
- All interactions between applications and a layer should occur via the interface of the layer.
- This interface should provide services that are well-suited for implementing applications that encompass its domain.
- Furthermore, the interface should be stable even if the implementation of the virtual machine might be subject to change.
-
Domain-specific services grouping:
- The set of services realized by a virtual machine should be selected based on the domain or domains of the applications it is intended to support.
To illustrate how applications use the interface of a layer to achieve specific goals, let's consider a few examples across different domains. These examples will demonstrate how applications interact with a layer's interface to utilize its services, ensuring that all interactions are encapsulated within the layer's interface.
Example 1: Database Access Layer
Scenario
An application needs to perform CRUD (Create, Read, Update, Delete) operations on a database. The database access layer provides an interface for these operations.
Database Access Layer Interface
class IDatabase {
public:
virtual ~IDatabase() = default;
virtual void connect(const std::string& connectionString) = 0;
virtual void disconnect() = 0;
virtual void executeQuery(const std::string& query) = 0;
virtual std::vector<std::string> fetchResults() = 0;
};
Implementation of Database Access Layer
class MySQLDatabase : public IDatabase {
public:
void connect(const std::string& connectionString) override {
// Implementation for connecting to MySQL database
}
void disconnect() override {
// Implementation for disconnecting from MySQL database
}
void executeQuery(const std::string& query) override {
// Implementation for executing a query on MySQL database
}
std::vector<std::string> fetchResults() override {
// Implementation for fetching results from MySQL database
return {};
}
};
Application Using the Database Access Layer
class Application {
public:
Application(IDatabase* db) : database(db) {}
void run() {
database->connect("connection_string");
database->executeQuery("SELECT * FROM users");
auto results = database->fetchResults();
for (const auto& result : results) {
std::cout << result << std::endl;
}
database->disconnect();
}
private:
IDatabase* database;
};
int main() {
MySQLDatabase db;
Application app(&db);
app.run();
return 0;
}
Example 2: Logging Layer
Scenario
An application needs to log messages for debugging and auditing purposes. The logging layer provides an interface for logging messages.
Logging Layer Interface
class ILogger {
public:
virtual ~ILogger() = default;
virtual void logInfo(const std::string& message) = 0;
virtual void logWarning(const std::string& message) = 0;
virtual void logError(const std::string& message) = 0;
};
Implementation of Logging Layer
class ConsoleLogger : public ILogger {
public:
void logInfo(const std::string& message) override {
std::cout << "[INFO] " << message << std::endl;
}
void logWarning(const std::string& message) override {
std::cout << "[WARNING] " << message << std::endl;
}
void logError(const std::string& message) override {
std::cout << "[ERROR] " << message << std::endl;
}
};
Application Using the Logging Layer
class Application {
public:
Application(ILogger* logger) : logger(logger) {}
void run() {
logger->logInfo("Application started");
// Perform some operations
logger->logWarning("This is a warning message");
// Perform some more operations
logger->logError("This is an error message");
logger->logInfo("Application finished");
}
private:
ILogger* logger;
};
int main() {
ConsoleLogger logger;
Application app(&logger);
app.run();
return 0;
}
Example 3: Network Communication Layer
Scenario
An application needs to send and receive data over the network. The network communication layer provides an interface for network operations.
Network Communication Layer Interface
class INetwork {
public:
virtual ~INetwork() = default;
virtual void connect(const std::string& address, int port) = 0;
virtual void disconnect() = 0;
virtual void sendData(const std::string& data) = 0;
virtual std::string receiveData() = 0;
};
Implementation of Network Communication Layer
class TCPNetwork : public INetwork {
public:
void connect(const std::string& address, int port) override {
// Implementation for connecting to a TCP server
}
void disconnect() override {
// Implementation for disconnecting from a TCP server
}
void sendData(const std::string& data) override {
// Implementation for sending data over TCP
}
std::string receiveData() override {
// Implementation for receiving data over TCP
return {};
}
};
Application Using the Network Communication Layer
class Application {
public:
Application(INetwork* network) : network(network) {}
void run() {
network->connect("127.0.0.1", 8080);
network->sendData("Hello, Server!");
auto response = network->receiveData();
std::cout << "Received: " << response << std::endl;
network->disconnect();
}
private:
INetwork* network;
};
int main() {
TCPNetwork network;
Application app(&network);
app.run();
return 0;
}
Summary
In these examples, the application interacts with different layers (database access, logging, network communication) through well-defined interfaces. These interfaces provide the necessary services for the application to achieve its goals. The implementation details of each layer are hidden behind the interface, ensuring that the application remains stable even if the underlying implementation changes. This approach promotes modularity, maintainability, and flexibility in software design.
标签:std,layer,string,Application,void,virtual,How,implement,network From: https://www.cnblogs.com/tortelee/p/18684621