我有一个名为IRegistrationService的客户端注册界面.这包含一个名为Register的方法,它通过类RegistrationService实现.如果我想要删除,更新,检索方法,我会为每个操作创建一个单独的接口,例如IDeletionService,IUpdateService,IRetrieveService,或者只是将所有方法放入IRegistrationService.我问这个的原因是因为这就是SOLID原则,特别是SRP原则似乎要问的问题.
关于stackoverflow的"开放封闭原则"主题已经有很多讨论.然而,似乎通常对该原理的更宽松的解释是普遍的,因此例如Eclipse可以通过插件进行修改.
根据严格的OCP,您应该修改原始代码只是为了修复错误,而不是添加新的行为.
在公共或OS库中是否有任何严格解释OCP的好例子,你可以通过OCP观察一个特征的演变:有一个类Foo,方法是bar(),而且还有一个FooDoingAlsoX和foo2()方法.库的下一个版本,其中原始类已被扩展,其中原始代码未被修改.
编辑:根据Robert C. Martin的说法:"模块的二进制可执行版本,无论是可链接库,DLL还是Java .jar都保持不变"*.我从未看到库保持关闭,实际上新的行为被添加到库中并且新版本已发布.根据OCP,新行为属于新的二进制模块.
*Robert C. Martin的敏捷软件开发,原则,模式和实践
我已经阅读了很多这方面的文章,但我还有两个问题.
问题#1 - 关于依赖性倒置:
它声明高级类不应该依赖于低级类.两者都应该取决于抽象.抽象不应该依赖于细节.细节应取决于抽象.
例如 :
public class BirthdayCalculator
{
private readonly List<Birthday> _birthdays;
public BirthdayCalculator()
{
_birthdays = new List<Birthday>();// <----- here is a dependency
}
...
Run Code Online (Sandbox Code Playgroud)
修复:把它放在一个ctor.
public class BirthdayCalculator
{
private readonly IList<Birthday> _birthdays;
public BirthdayCalculator(IList<Birthday> birthdays)
{
_birthdays = birthdays;
}
Run Code Online (Sandbox Code Playgroud)
如果它将在ctor中 - 我将不得不每次使用该课程时发送它.所以在打电话给BirthdayCalculator班级时我必须保留它.它可以这样做吗?
我可以争辩说,在修复之后,仍然 - IList<Birthday> _birthdays不应该在那里(Birthdayin IList) - 但它应该是IList<IBirthday>.我对吗 ?
问题#2 - 关于利斯科夫换人:
派生类必须可替代其基类
或更准确:
设q(x)是关于类型T的对象x可证明的属性.对于类型S的对象y,q(y)应该为真,其中S是T的子类型.
(已经读过这个)
例如:
public …Run Code Online (Sandbox Code Playgroud) c# design-patterns liskov-substitution-principle inversion-of-control solid-principles
在查看维基百科文章后,我对"子类型"一词不熟悉.
我把Liskov替换意味着,如果你有接受一个方法Animal,你应该能够在通过Cat或Animal在那里Cat : Animal没有任何意想不到的副作用.
这是Liskov替换所指的吗?
在经典的Facade模式中,单个对象通常为更复杂的东西提供简化的界面.
正如四人帮所说的那样(尽管接近"官方"......):
Facade(185)为子系统中的一组接口提供统一接口.Facade定义了一个更高级别的接口,使子系统更易于使用.
和
...一个外观只是抽象出子系统对象的接口,使它们更容易使用; 它没有定义任何新功能,子系统类也不知道它.
或者,正如Unmesh将其放在/sf/answers/366973351/中:
Facade保护用户免受系统的复杂细节的影响,并为他们提供易于使用的简化视图.它还将使用系统的代码与子系统的细节分离,使以后更容易修改系统.
单一责任原则告诉我们
一个类或模块应该只有一个改变的理由.
Per Bob叔叔(http://en.m.wikipedia.org/wiki/Single_responsibility_principle)
鉴于Facade在设计上可以保护用户免受众多"改变的原因"的影响,这两个想法如何协同工作?Facade是否有与其实现所依赖的子系统数量一样多的理由进行更改?
oop design-patterns single-responsibility-principle facade solid-principles
我正在研究单一职责原则(SRP)和开闭原则(OCP)。
SRP 规定,一个类必须只有一个改变的理由。OCP 规定类必须对修改关闭,但对扩展开放。
我觉得这是矛盾的。一个原则规定类必须足够简单,您可以出于单一原因进行更改,但另一条原则规定类不得更改而只能扩展。
有人有更好的解释吗?
我试图遵循接口隔离和单一职责原则,但是我对如何将它们整合在一起感到困惑。
在这里,我有一个示例,其中有一些接口,我已将其拆分为更小、更直接的接口:
public interface IDataRead
{
TModel Get<TModel>(int id);
}
public interface IDataWrite
{
void Save<TModel>(TModel model);
}
public interface IDataDelete
{
void Delete<TModel>(int id);
void Delete<TModel>(TModel model);
}
Run Code Online (Sandbox Code Playgroud)
我稍微简化了它(有一些where条款妨碍了可读性)。
目前我正在使用SQLite ,但是,这种模式的美妙之处在于,如果我选择不同的数据存储方法(例如Azure),它有望让我有机会更好地适应变化。
现在,我对每个接口都有一个实现,下面是每个接口的简化示例:
public class DataDeleterSQLite : IDataDelete
{
SQLiteConnection _Connection;
public DataDeleterSQLite(SQLiteConnection connection) { ... }
public void Delete<TModel>(TModel model) { ... }
}
...
public class DataReaderSQLite : IDataRead
{
SQLiteConnection _Connection;
public DataReaderSQLite(SQLiteConnection connection) { ... }
public …Run Code Online (Sandbox Code Playgroud) c# interface single-responsibility-principle solid-principles interface-segregation-principle
我有我的代码根据请求类型进行Web服务调用.
为此,我有以下代码;
public class Client
{
IRequest request;
public Client(string requestType)
{
request = new EnrolmentRequest();
if (requestType == "Enrol")
{
request.DoEnrolment();
}
else if (requestType == "ReEnrol")
{
request.DoReEnrolment();
}
else if (requestType == "DeleteEnrolment")
{
request.DeleteEnrolment();
}
else if (requestType == "UpdateEnrolment")
{
request.UpdateEnrolment();
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以按照开放原则,我可以像子类一样子类:
Class EnrolmentRequest:IRequest
{
CallService();
}
Class ReEnrolmentRequest:IRequest
{
CallService();
}
Class UpdateEnrolmentRequest:IRequest
{
CallService();
}
Run Code Online (Sandbox Code Playgroud)
现在我的客户端类看起来像这样:
public class Client
{
public Client(string requestType)
{
IRequest request;
if (requestType == "Enrol") …Run Code Online (Sandbox Code Playgroud) .net c# dependency-injection inversion-of-control solid-principles
我只是想知道IS-A(UML术语和OOP)和Liskov替换原则(LSP)之间是否存在差异?
实际上,两者都在谈论继承.那么实践中的主要区别是什么?
oop inheritance liskov-substitution-principle solid-principles
我有 3 个班级,Account, CappedAccount, UserAccount,
CappedAccount,并且UserAccount都扩展Account。
Account 包含以下内容:
abstract class Account {
...
/**
* Attempts to add money to account.
*/
public void add(double amount) {
balance += amount;
}
}
Run Code Online (Sandbox Code Playgroud)
CappedAccount 覆盖此行为:
public class CappedAccount extends Account {
...
@Override
public void add(double amount) {
if (balance + amount > cap) { // New Precondition
return;
}
balance += amount;
}
}
Run Code Online (Sandbox Code Playgroud)
UserAccount不会覆盖来自 的任何方法Account,因此不需要说明。
我的问题是,是否CappedAccount#add …
solid-principles ×10
oop ×7
c# ×4
liskov-substitution-principle ×2
single-responsibility-principle ×2
.net ×1
facade ×1
inheritance ×1
interface ×1
interface-segregation-principle ×1
java ×1