在本文中,我想阐明一下对所使用组件类型的紧密依赖。 通常,我们的目标是设计类,以使它们通过接口或更通常通过API进行交互。 假设我们使用接口(更多的通用术语是我们没有实现,不是特定于Java或C#中的关键字接口),但这还不够,我们需要为接口实际提供某种实现,其他客户端类。
在详细介绍之前,让我选择一些示例(Java中的示例):我想设计一个Reader,它可以帮助客户端类从指定的任何来源(文件系统/ Web)中获取信息。 因此,接口为:
interface Reader
{
public String read();
/**
* Get the source to read from
*/
public String getSource();
}
我希望用户无缝使用API从文件系统或Web / Web文档中读取文件。 下一步将是创建从文件系统和Web读取的实现。
class FileSystemReader implements Reader
{
private String source;
public FileSystemReader(String source)
{
this.source = source;
}
@override
public String getSource()
{
return this.source;
}
public String read()
{
//Read from the source.
//The source is a file in file system.
}
}
class HttpReader implements Reader
{
private String source;
public FileSystemReader(String source)
{
this.source = source;
}
@override
public String getSource()
{
return this.source;
}
public String read()
{
//Read from the source.
//The source is a document in the web.
}
}
使用这些接口和实现的一种方法是-客户端类根据源格式确定要实例化的实现。 因此,它将类似于:
class Client
{
/**
* This is the consumer of the Reader API
* @param source Source to read from
*/
public void performSomeOperation(String source)
{
Reader myReader = null;
if(source contains "http://")
{
//its a web document, create a HttpReader
myReader = new HttpReader(source);
}
else
{
myReader = new FileReader(source);
}
print(myReader.read());
}
}
一切看起来不错,这些类通过API相互交互,但是您可能会觉得不好。 然后是另一个要求,在其中可以找到第三个来源,您必须在所有进行此类创建的地方进行更改。 如果您错过了某个地方的更改,那么您将得到一个损坏的代码,请看您的代码变得多么脆弱。
除此之外,您的客户端类还知道HttpReader用于此操作,而FileReader则用于该操作,因此您将放弃与所使用实例有关的类型相关的信息,从而使客户端代码与该类型信息紧密结合。 这种方法有时会破坏开放式封闭原则,因为每次添加新的接口实现时,您最终都要编辑类。 因此,应该有某种方式我们可以屏蔽这些接口的用户对接口的不同实现的实例的创建。 是的,有很多方法,我知道到现在您必须等待释放工厂方法模式 。
那么如何将以上代码修改为使用Factory
/**
* Factory to get the instance of Reader implementation
*/
class ReaderFactory
{
public static getReader(String source)
{
if( source contains http)
{
return new HttpReader(source);
}
else if(someother condition)
{
return new SomeReader(source);
}
else
{
return new FileReader(source);
}
}
}
class Client
{
/**
* This is the consumer of the Reader API
* @param source Source to read from
*/
public void performSomeOperation(String source)
{
Reader myReader = ReaderFacotry.getReader(source);
print(myReader.read());
}
}
看看客户端代码变得多么简单,没有类型相关的噪音,用户将不需要知道正在使用哪种类型的实例,从而使自身与类型的耦合减少。 factory方法负责根据源字符串中的模式查看是否返回客户端代码的实现。 这样,由于公开类型信息,最终导致耦合方面的耦合代码较少。 现在,当有新的需求要求新的读者来获取新的资源时,您便知道必须在哪里进行更改,并且更改将只在一个地方进行。 您可以看到您的代码不那么脆弱,并且您已经从代码中消除了不必要的冗余。
要记住的一件事是,封装不仅隐藏数据,而且隐藏用户的类型相关信息。
参考:来自JCG合作伙伴的 面向对象范式耦合的另一个方面 体验无限博客上的Mohamed Sanaulla。
翻译自: https://www.javacodegeeks.com/2012/02/another-aspect-of-coupling-in-object.html