策略模式和适配器模式的区别

18
为什么策略设计模式和适配器模式相关?在我看来,适配器模式修改了某个方法的结果以满足另一个方法的输入需求。而策略模式则规定了行为方式。
3个回答

41

适配器模式基本上允许那些本身由于接口不兼容而无法工作在一起的类协同工作。适配器将一个类的接口转换为另一个类可使用的接口。

就像当你出国旅行时需要携带电源适配器才能使用墙上的插座。

另一方面,策略模式采用一组算法,并使它们可互换(通过扩展公共接口)。因此,无论要使用策略的类是什么,都可以轻松地与该组中的另一个策略交换。

换句话说,适配器不以任何方式添加行为,只是修改现有接口以使其他某个类可以访问现有功能。

另一方面,策略模式封装了不同的行为,并允许在运行时切换它们。


1
策略模式: https://www.journaldev.com/1754/strategy-design-pattern-in-java-example-tutorial 适配器模式: https://www.journaldev.com/1487/adapter-design-pattern-java - Vardaan Sharma
2
如果需要,可以使用适配器来从不兼容的接口添加新策略。 - Vikram Singh
@VikramSingh 我认为那应该是答案。适配器是拥有多种策略的方法之一。 - Code Name Jack
适配器不会以任何方式添加行为... 是的,这应该是主要观点。 - Sajithd

2
一个例子总是很好,让我们来看一个适配器的用例。想象一下你正在使用一个你不能修改的包,它包含以下文件:
class DatabaseManager
{
   private Connection $connection;

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


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

在您的代码库中,您有以下代码:

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

一切都运行良好,但是当你需要将连接更改为SqlLiteConnection并添加导入不同包以使用它时,就会出现问题。导入的文件如下:

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

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

SqlLiteConnection的接口(方法名称)与MysqlConnection不同,因此您在使用它时遇到了麻烦:

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

你无法修改SqlLiteConnection包,因此为了让它正常工作,你需要创建一个适配器:

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


现在它可以工作了!
class YourService
{
   public function connectDB()
   {
      $db = new DatabaseManager();
      $db->connect(new SqlLiteAdapter(new SqlLiteConnection())); //works!
   }
}


如您所见,适配器仅被用作别名将 "establish" 映射到方法 "prepareConnection" 和 "executeConnection"。这就是适配器的目的,它不会添加功能,而只是使接口适应您的需要。类似于旅行适配器,让您可以在欧盟插座上使用美国插头。
另一方面,策略模式的实现与上述类似,但您不仅仅在适配器中进行一些函数映射,而且还要为每个策略添加您的独特逻辑。

0

适配器(Adapter)是指在不修改行为的情况下使用现有函数。策略(Strategy)则根据当前使用的具体类来修改其行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接