简体   繁体   中英

Difference between Strategy Pattern and Adapter

Why is the strategy design pattern and the adapter related to each other? It seams to me that the adapter manipulates the result of some method to fullfill the input needs of anotherone. Wheras the strategy precibes behaviour.

Adapter patterns basically allows classes to work together that on their could not due to incompatible interfaces. Adapter converts the interface of one class into something that may be used by another class.

Similar to how if you travel abroad you need to carry a power adapter to be able to use the wall sockets.

Strategy pattern, on the other hand takes a group of algorithms, and makes them interchangeable (by extending from a common interface). So that whatever class that is going to use the strategy can easily interchange it with another strategy from the group.

In other words, Adapter does not add behavior in any way, it just modifies the existing interface to allow some other class to access the existing functionality.

Strategy pattern on the other hand encapsulates different behavior, and allows them to be switched at run time.

An example is always good, lets take a look at a use case for an adapter. Imagine you have are using some package you cannot modify, it contains the following files:

class DatabaseManager
{
   private Connection $connection;

   public function connect(Connection $connection)
   {
      $this->connection = $connection->establish();
   }
}

class MysqlConnection implements Connection
{
    public function establish(){
       // connect to mysql...
    }
}

Inside your repo you have the following code:

class YourService
{
   public function connectDB()
   {
      $db = new DatabaseManager();
      $db->connect(new MysqlConnection());
   }
}

It all works fine, however then you get the requirement to change the connection to SqlLiteConnection and add have to import a different package for using it. The imported file looks like this:

class SqlLiteConnection
{
    public function prepareConnection(){
       // first prepare the connection...
       return $preparedConnection;
    }

    public function executeConnection($preparedConnection){
       // then connect ...
       $preparedConnection->execute();
    }
}

The interface (method names) of SqlLiteConnection is different to MysqlConnection, so you are having trouble using it:

class YourService
{
   public function connectDB()
   {
      $db = new DatabaseManager();
      $db->connect(new SqlLiteConnection()); // error! method `establish` does not exist in SqlLiteConnection.
   }
}

You are not able to modify the SqlLiteConnection package, so to get it to work you create an adapter:

class SqlLiteAdapter implements Connection
{
   public function establish($sqlConnection)
   {
      $preparedConnection = $sqlConnection->prepareConnection();
      $sqlConnection->executeConnection(preparedConnection);
   }
}

Now it works!

class YourService
{
   public function connectDB()
   {
      $db = new DatabaseManager();
      $db->connect(new SqlLiteAdapter(new SqlLiteConnection())); //works!
   }
}

As you can see the adapter was just used as an alias to map establish to the methods prepareConnection and executeConnection . This is the purpose of an adapter, it does not add functionality but just adapts the interface to your needs. Similar to a travel adapter that allows you to use a US plug in a EU socket.

The strategy pattern on the other hand would have a similar implementation as above but you would not simply map some functions in the Adapter but would add your unique logic for each of your Strategies.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM