Factory Method模式如何在这种情况下使代码易于维护

huangapple go评论56阅读模式
英文:

How Factory Method pattern make code maintainable in this case

问题

I'm new to design patterns, I was reading a book says:
在一个应用程序中,你可能有不同的数据库用户。例如,一个用户可能使用Oracle,另一个用户可能使用SQL Server。每当你需要向数据库插入数据时,你需要创建一个SqlConnection或一个OracleConnection,然后才能继续。如果你将代码放入if-else(或switch)语句中,你需要重复大量的代码,这不容易维护。这是因为每当你需要支持新类型的连接时,你需要重新打开你的代码并进行修改。这种问题可以使用工厂方法模式来解决。

I'm a little bit confused here, if you need to use a new type of connection, don't you just add a new class file of that connection class (e.g. NEWGenerationConnection), then just use NewGenerationConnection connection = new NewGenerationConnection(connectionString); connection.open(); ....
how does if-else get involved here? and why you need to modify the base code file? can someone write some pseudo code for me so that I can understand the problem better?

我对此感到有些困惑,如果你需要使用新类型的连接,难道你不只是添加一个新的连接类文件(例如NEWGenerationConnection),然后只需使用 NewGenerationConnection connection = new NewGenerationConnection(connectionString); connection.open(); ....
if-else 如何介入?为什么需要修改基本代码文件?能否有人为我编写一些伪代码,以便我更好地理解这个问题?

英文:

I'm new to design patterns, I was reading a book says:
In an application, you may have different database users. For example, one user may use
Oracle, and the other may use SQL Server. Whenever you need to insert data into your
database, you need to create either a SqlConnection or an OracleConnection and only
then can you proceed. If you put the code into if-else (or switch) statements, you need to repeat a lot of code, which isn’t easily maintainable. This is because whenever you
need to support a new type of connection, you need to reopen your code and make those
modifications. This type of problem can be resolved using the Factory Method pattern.

I'm a little bit confused here, if you need to use a new type of connection, don't you just add a new class file of that connection class (e.g.

NEWGenerationConnection), then just use NewGenerationConnection connection = new NewGenerationConnection(connectionString);
connection.open();
....

how does if-else get involved here? and why you need to modify the base code file? can someone write some pseudo code for me so that I can understand the problem better?

答案1

得分: 1

以下是您要翻译的内容:

这里的重点是集中代码块,具有可能发生更改的可能性。如果你在多个类中散布相同的if-else块,那么如果以后需要对它进行更改,你必须在所有地方进行更改。虽然IDE提供了查找和替换实用工具,但即使在这种情况下,这也不是一个好的做法,至少因为分开编译。

通过工厂模式,你将if-else逻辑放在一个地方,并将从工厂获取的多态超类型对象传递给你的类,然后你可以使用动态分派的好处,例如策略或模板方法模式。

让我们看一个示例(为了简洁起见,这是一个基本示例,所以我没有重构不相关的内容):

public class ConnectionPolicyFactory {

    public ConnectionPolicy getPolicy(String dbVendor) {
        if (dbVendor == "ORACLE") {
            return new OracleConnectionPolicy();
        } else if (dbVendor == "SQL_SERVER") {
            return new SqlServerConnectionPolicy();
        }
        //异常情况
    }

}

然后在客户端:

ConnectionPolicyFactory connectionPolicyFactory = new ConnectionPolicyFactory();

//这是Connection类型的父类。
ConnectionPolicy connectionPolicy = connectionPolicyFactory.getPolicy("ORACLE");//这是OracleConnectionPolicy

MyClass myClass = new MyClass();
myClass.foo(connectionPolicy);

然后在您的类中,也许您正在做这样的事情:

public class MyClass {
   //...
   
   public void foo(ConnectionPolicy conn) {
      conn.someVendorSpecificAction();
   }

   //...
   
}

如果你没有使用工厂,并且当你可能有更多使用这个ConnectionPolicy的类时,你将在所有类中拥有所有if-else逻辑。

英文:

The point here is centralizing the code blocks having possibility of change. If you scatter same if-else blocks around multiple classes then if a change needs on it later, you have to make changes in all places. An IDE offers you find and replace utility, but even in this case it is not a good practice at least because of separate compilation.

With factory pattern you put that if-else logic in one place and pass the object which is a polymorphic super type you get from the factory to your classes and then you will use the benefits of dynamic dispatch with for example strategy or template method patterns.

Let's see in example(for the sake of brevity it's a basic example so I did't refactor for unrelated stuff):

public class ConnectionPolicyFactory {

    public ConnectionPolicy getPolicy(String dbVendor) {
        if (dbVendor == "ORACLE") {
            return new OracleConnectionPolicy();
        } else if (dbVendor == "SQL_SERVER")) {
            return new SqlServerConnectionPolicy();
        }
        //exceptional cases
    }

}

then in the client:

ConnectionPolicyFactory connectionPolicyFactory = new ConnectionPolicyFactory();

//this is the parent of Connection types.
ConnectionPolicy connectionPolicy = connectionPolicyFactory.getPolicy("ORACLE");//which is OracleConnectionPolicy

MyClass myClass = new MyClass();
myClass.foo(connectionPolicy);

then in your class maybe you are doing something like:

public class MyClass {
   //...
   
   public void foo(ConnectionPolicy conn) {
      conn.someVendorSpecificAction();
   }

   //...
   
}

If you didn't use a factory and when you probably had more classes using this ConnectionPolicy then you would have all if-else logics in all your classes.

huangapple
  • 本文由 发表于 2020年1月6日 22:47:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/59614102.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定