如果使用装饰器或外观模式来满足我的需求,我将面临一个问题。
想象一个客户想要播放一段视频。他可以使用这个接口
public interface IVideoPlayer
{
// Prepares everything to set up and plays the video
void Play();
}客户端不应该关注准备工作,因此接口方法的总结说明准备工作是由Play()方法完成的。
准备工作可能包括连接到互联网、登录到服务等不同的内容。对于不同的系统有不同的制备步骤。
我可以使用外观模式实现IVideoPlayer,如下所示
VideoPlayerFacade : IVideoPlayer
{
ctor(...)
void Play()
{
_internetConnection.Connect();
_loginService.Login();
_actualVideoPlayer.Play();
}
}我不喜欢这种方法:
CreateCar()委托给CreateEngine()、CreateCarBody()等等。_actualVideoPlayer实现的接口类型也可以命名为IVideoPlayer,因为它是实际的视频播放器,它也指导我使用装饰器模式。我需要两个几乎相同的接口(一个没有准备,一个没有准备),它们的名字非常相似,我现在无法想象。可以使用实际的播放算法实现IVideoPlayer,如下所示
VideoPlayer : IVideoPlayer
{
void Play()
{
// do stuff and algorithms
}
}准备工作可以由装修人员完成,如下所示
PreparatingVideoPlayer : IVideoPlayer
{
ctor(...)
void Play()
{
_internetConnection.Connect();
_loginService.Login();
_decoratee.Play();
}
}我不喜欢这种方法:
VideoPlayer违反了Play()方法,因为它不符合接口,没有在D25方法中做好所有准备工作,这反而导致了facade模式。或者它是否违反了LSP,因为当它被注入到系统中时,它总是由PreparatingVideoPlayer来修饰?IVideoPlayer被注入总是会导致获得PreparatingVideoPlayer,这将使我再次进入外观模式。那么,哪一种模式更合适,或者这些模式根本不合适?我的担心有效吗?
发布于 2018-11-21 18:53:12
让我们开始吧:我讨厌你的第二个解决方案。
IVideoPlayer是一个接口,是任何实现类都会做某种事情的“契约”。这是一个代码方面的契约(调用者和实现之间的契约),但在某种程度上也是程序员之间的人际关系--如果我用IVideoPlayer擦除硬盘驱动器,编译器就不会阻止我。
<#>The 2实现不是履行相同的契约,它们只是有一个同名的方法。
这里没有给出接口应该提供的安全性。更糟糕的是,由于对这样一份合同的期望,这使得更有可能有人会弄错它。
有计算机科学中的2件难事,其中之一就是命名东西。不要低估它,词库是最被低估的编程工具之一。您应该有两个不同的名称来表示这两个实现之间的区别。
举个例子,您可以将“外部”一个重命名为VideoSystem:一个是整个系统,另一个只是玩家。或者您可以重命名内部的一个VideoRenderer:一个是整个播放器,而另一个只是部分“渲染”视频。
由于外部API似乎是公开的API,我宁愿重命名内部API,因为您可以更容易地向同事解释内部API,而不是向客户解释外部API。
维基百科提到了装饰模式。
装饰设计模式能解决哪些问题?
关于外观模式,维基百科说
立面设计模式能解决哪些问题?
这两个目标都不是你的目标。
您不需要这样做,因为您希望在运行时动态地添加或删除事物,或者希望扩展功能,或者因为您的子系统太难使用,或者您对子系统有太多的依赖关系。
首先,您正在尝试创建一些功能。
不要想“我应该采用哪种模式”。做有效的事。最后,您的代码可能是一个已经建立的模式,然后当您的同事询问代码时,您可以告诉他们“我用{模式名称}解决了它”。这就是你从使用模式中获得的所有优势。
所有这些话,做第一件事。
但是,调用facade可能会让人感到困惑,因为很多 人的数量将外观看作是相当简单的类,只是“传递”方法(例如,如果您也有一个调用_internetConnection.Connect();的方法Connect() )。维基百科的例子不这么说,但它们似乎并不特别好(例如,反复使用在构造函数中调用新闻)。
你有一个VideoPlayer类,为了完成它的工作,它需要其他类--我把它叫做好的旧作文。如果你把它叫做作文,没人会误解你的。
https://softwareengineering.stackexchange.com/questions/381803
复制相似问题