如何通过设计模式改进多态性
我正在尝试设计一个允许处理多种类型文件的系统。这个想法是,有一个应用程序来处理磁盘上文件的实际操作,而开发人员可以编写自定义库,这些库将能够在加载后对文件执行任何他们想要的操作。
我当前的结构如下所示:
应用程序发布一个 IClient
接口,自定义编写的库可以自由实现该接口。 Client1
到 Client3
都有不同的实现,并以不同的方式响应每种类型的文件。
File
上的 Populate
方法在派生类中被重写,以调用 IClient
接口上正确的 PopulateFrom
方法,传入调用文件。
因此,实现 IClient
的类上的 PopulateFrom
方法会传递一个特定类型的文件,以便它必须访问底层数据(CSVDataReader
或本例中的 XDocument
)解析为它想要的任何特定于域的对象。
对于添加到系统中的每种新文件类型使用此设计,我必须向 IClient
添加一个新方法,这并不理想。为了保持与没有接受新文件类型的方法的客户端类的兼容性,我必须创建一个专门支持该类型的新接口,并让新客户端实现:
这一切都有效,但我想知道是否有更好的方法来支持多种文件类型,而无需每次都必须添加新界面,可能使用设计模式吗?
I'm attempting to design a system that will allow the processing of multiple types of file. The idea being that there's a single application to handle the actual manipulation of the files on disk, while developers can write custom libraries that will be able to do whatever they want with the files once loaded.
I current have a structure that looks like this:
Where the application publishes an IClient
interface that the custom written libraries are free to implement. Client1
to Client3
would each have a different implementation and respond to each type of file in a different way.
The Populate
method on File
is overriden in the derived classes to call the correct PopulateFrom
method on the IClient
interface, passing in the calling file.
Therefore the PopulateFrom
method on the class implementing IClient
is passed a file of a specific type so that it has to access the underlying data (CSVDataReader
or XDocument
in this example) to parse into whatever domain-specific objects it wants.
Using this design for every new type of file I add to the system I would have to add a new method to IClient
which isn't ideal. To preserve compatibility with the client classes that don't have the method accepting the new file type I'm going to have to create a new interface that specifically supports that type and have the new client implement that:
That all works, but I was wondering whether there's a better way of supporting the multiple file types without having to add a new interface every time, possibly using a design pattern?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里有一个选项:您的
PopulateFrom
方法不应采用特定的文件类型,而应采用FileStream
或MemoryStream
,毕竟是一个文件只是一个字节流,正是这些字节的组织使每种文件类型都是唯一的。此外,您可能想要实现与此类似的方法:
这样您可以以通用方式查询每个提供程序,它会告诉您它是否可以处理该特定文件。通过这种方式,您可以实现更多的文件类型和更多的提供程序,而不必扩展您的接口或扰乱现有的提供程序。
查看提供者模式看看是否有帮助。
Here is an option: your
PopulateFrom
method should not take a specific file type, instead it should take aFileStream
orMemoryStream
, after all a file is simply a stream of bytes, it is the organisation of those bytes that makes each file type unique.Additionally, you may want to implement a method similar to this:
that way you can query each provider in a generic way and it will tell you if it can process that particular file. Doing it this way will allow you to implement more file types and more providers without having to extend your interface or mess with the existing providers.
Check out the Provider pattern to see if it helps.
您的设计违反了称为依赖倒置的设计原则,因为客户端依赖于具体类而不是抽象类。
您应该重新考虑以使用抽象类型(Application::File)的方式来实现您的客户端。如果绝对没有办法做到这一点,那么您应该重新设计类层次结构。
想一想。如果很少使用抽象,那么它可能毫无用处。罗伯特·马丁将此称为稳定抽象原则。
Your design violates the design principle known as Dependency inversion, because clients depend on concrete classes instead of abstract ones.
You should reconsider implementing your clients in a way they work with the abstract type (Application::File). If there's absolutely no way to do that, then you should redesign the class hierarchy.
Think about it. If an abstraction is seldom used then it is probably useless. Robert Martin terms this as the Stable abstractions principle.