标签: open-closed-principle

开放/封闭原则背后的含义和推理是什么?

开放/封闭原则规定软件实体(类,模块等)应该是可以扩展的,但是对于修改是封闭的.这意味着什么,为什么它是良好的面向对象设计的重要原则?

oop definition design-principles open-closed-principle solid-principles

42
推荐指数
7
解决办法
6246
查看次数

在Bootstrapper中配置Automapper违反了开放封闭原则?

我在引导程序配置Automapper和我打电话Bootstrap()Application_Start(),我一直在说,这是错误的,因为我要修改我的Bootstrapper每一次我必须添加一个新的映射类,所以我违反了开闭原则.

你觉得怎么样,我真的违反了这个原则吗?

public static class Bootstrapper
{
    public static void BootStrap()
    {
        ModelBinders.Binders.DefaultBinder = new MyModelBinder();
        InputBuilder.BootStrap();
        ConfigureAutoMapper();
    }

    public static void ConfigureAutoMapper()
    {
        Mapper.CreateMap<User, UserDisplay>()
            .ForMember(o => o.UserRolesDescription,
                       opt => opt.ResolveUsing<RoleValueResolver>());
        Mapper.CreateMap<Organisation, OrganisationDisplay>();
        Mapper.CreateMap<Organisation, OrganisationOpenDisplay>();
        Mapper.CreateMap<OrganisationAddress, OrganisationAddressDisplay>();
    }    
}
Run Code Online (Sandbox Code Playgroud)

.net bootstrapping automapper open-closed-principle solid-principles

35
推荐指数
1
解决办法
9710
查看次数

访客模式如何不违反开放/封闭原则?

来自维基百科:

这个想法是,一旦完成,只能修改类的实现以纠正错误; 新功能或更改功能需要创建不同的类.该类可以通过继承重用原始类中的编码

根据我的理解,访问者模式是一种强大的技术,可以遍历使用双重调度实现相同接口的相似但不同的对象.在我的一个Java示例中,我创建了一组形成树结构的复合对象,这些对象的每个特定实现都实现了可访问的接口.访问者界面具有用于每个可访问对象的方法,并且具体访问者实现对每个这些情况执行的操作.

我试图解决的问题是,如果我要在复合结构中添加一个也实现可访问的新实现,那么我需要重新打开访问者界面并将该情况添加到它,也迫使我修改访问者的每个实现.

虽然这很好,但我还是需要这样做(如果访问者无法理解,那么访问者增加了什么好处?)但是在学术层面上,这不会违反开放封闭原则吗?这不是设计模式的核心原因之一吗?试图显示转换到这种模式的合理理由而不是维护switch语句来结束所有switch语句,但是每个人都认为代码将是相同的,每种情况的方法而不是交换机块,只是分解并且更难阅读.

java design-patterns visitor open-closed-principle

27
推荐指数
2
解决办法
2046
查看次数

开放封闭原则和Java"最终"修饰符

开放封闭原则指出"软件实体(类,模块,功能等)应该是可以扩展的,但是对于修改是封闭的".

然而,Joshua Bloch在其着名的书"Effective Java"中给出了以下建议:"继承的设计和文档,或者禁止它",并鼓励程序员使用"final"修饰符来禁止子类化.

我认为这两个原则显然是相互矛盾的(我错了吗?).编写代码时遵循哪个原则,为什么?你是否打开你的课程,不允许继承你的课程(哪些?),或者尽可能使用最终修饰语?

java open-closed-principle

22
推荐指数
5
解决办法
5054
查看次数

访客模式+开放/封闭原则

是否可以实现尊重开放/封闭原则访客模式,但仍然能够添加新的可访问类?

开放/封闭原则规定"软件实体(类,模块,功能等)应该开放以进行扩展,但是关闭以进行修改".

struct ConcreteVisitable1;
struct ConcreteVisitable2;

struct AbstractVisitor
{
   virtual void visit(ConcreteVisitable1& concrete1) = 0;
   virtual void visit(ConcreteVisitable2& concrete2) = 0;
};

struct AbstractVisitable
{
   virtual void accept(AbstractVisitor& visitor) = 0;
};

struct ConcreteVisitable1 : AbstractVisitable
{
   virtual void accept(AbstractVisitor& visitor)
   {
      visitor.visit(*this);
   }
};

struct ConcreteVisitable2 : AbstractVisitable
{
   virtual void accept(AbstractVisitor& visitor)
   {
      visitor.visit(*this);
   }
};
Run Code Online (Sandbox Code Playgroud)

您可以实现任意数量的派生自AbstractVisitor的类:它是可以扩展的.您无法添加新的可访问类,因为从AbstractVisitor派生的类将无法编译:它已关闭以进行修改.

AbstractVisitor类树遵循开放/封闭原则.AbstractVisitable类树不遵循开放/封闭原则,因为它无法扩展.

除了扩展AbstractVisitor和AbstractVisitable之外还有其他解决方案吗?

struct ConcreteVisitable3;

struct AbstractVisitor2 : AbstractVisitor
{
   virtual void visit(ConcreteVisitable3& concrete3) = 0;
};

struct …
Run Code Online (Sandbox Code Playgroud)

c++ oop design-patterns visitor-pattern open-closed-principle

16
推荐指数
1
解决办法
1690
查看次数

避免如果其他条件

我想重构以下代码以避免if ... else以便每次进入新的调查类型时都不必更改方法(开放/封闭原则).以下是我正在考虑重构的一段代码:

if (surveyType == SurveySubType.Anonymous)
{
    DoSomething(param1, param2, param3);

}
else if (surveyType == SurveySubType.Invitational)
{
    DoSomething(param1);
}
else if (surveyType == SurveySubType.ReturnLater)
{    
    DoSomething(param1);
}
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我添加了以下类:

    public abstract class BaseSurvey
{
            public string BuildSurveyTitle()
            {
             ...doing something here
            }

    public abstract void DoSomething(int? param1,int?  param2,int?  param3);
}
public class InvitationalSurvey: BaseSurvey
{
    public override void DoSomething(int? param1,int?  param2,int?  param3)
    {
    //I don't need param2 and param3 here

    }
}


public class ReturnLaterSurvey: BaseSurvey
{
    public override void …
Run Code Online (Sandbox Code Playgroud)

c# oop open-closed-principle solid-principles

15
推荐指数
2
解决办法
2307
查看次数

清除代码以删除开关条件(使用多态)

正如SOLID原则所说,最好通过将切换条件转换为类和接口来删除它们.我想用这段代码做:

注意:这段代码不是真正的代码,我只想把它放进去.

MessageModel message = getMessageFromAnAPI();
manageMessage(message);
...
void manageMessage(MessageModel message){        
    switch(message.typeId) {
        case 1: justSave(message); break;
        case 2: notifyAll(message); break;
        case 3: notify(message); break;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我想删除switch语句.所以我为它创建了一些类,我尝试在这里实现一个多态:

interface Message{
    void manageMessage(MessageModel message);
}
class StorableMessage implements Message{

    @Override
    public void manageMessage(MessageModel message) {
        justSave(message);
    }
}
class PublicMessage implements Message{

    @Override
    public void manageMessage(MessageModel message) {
        notifyAll(message);
    }
}
class PrivateMessage implements Message{

    @Override
    public void manageMessage(MessageModel message) {
        notify(message);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我调用我的API来获取我的MessageModel:

MessageModel message = getMessageFromAnAPI(); …
Run Code Online (Sandbox Code Playgroud)

java open-closed-principle solid-principles

14
推荐指数
3
解决办法
4495
查看次数

打开/关闭原则 - 如何调用新版本?

我正在尝试掌握开放/封闭原则(在我的情况下是PHP,但这并没有真正有所作为).

我理解的方式是一个类永远不会被修改.仅用于修复错误.如果我想在课程中添加新代码,那么我必须创建一个新代码并扩展"旧"类.这是我可以添加新代码的唯一方法.

在某种程度上,我可以看到这种优势.因为基本上你创建了某种版本控制系统,旧代码总是可以工作,但你总是可以尝试使用新类.

但这在实践中如何运作?我的意思是,假设我有以下课程:

class MyObject
{
    public function doSomething()
    {
        echo 'Im doing something';
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我可能在某个地方实例化这个类:

$obj = new MyObject();
Run Code Online (Sandbox Code Playgroud)

但后来我决定在该对象中使用另一种方法是件好事.所以我也可以做其他事情.根据OCP,我无法修改课程.所以我必须创建一个新的,延伸到旧的一个吧?

第一个问题.我怎么称呼新课程?因为它实际上不是一个完整的新对象.喜欢.User对象是User对象.我不能突然给它完全不同的名称,因为它需要另一种方法.无论如何,我创建了新类:

class MyNewObject extends MyObject
{
    public function doSomethingElse()
    {
        echo 'Im doing something else now';
    }
}
Run Code Online (Sandbox Code Playgroud)

现在这也意味着我必须更改我实例化"MyObject"类的代码行,并将其替换为"MyNewObject"类,对吧..?如果在不止一个地方完成,那么我必须搜索我的源代码...(想想控制器类中的方法,它几乎总是使用'​​new'关键字来实例化某些类).

这基本上适用于继承.我必须找到继承旧类的每个类,并且必须用新类替换它.


基本上我的问题是:

你如何命名具有新方法的新类?只是因为我添加了一些新功能,并不意味着我可以给全班一个全新的名字......

如果"旧"类从多个地方实例化(或继承),该怎么办?然后我必须找到所有这些地方......收益在哪里?

php oop open-closed-principle

12
推荐指数
1
解决办法
292
查看次数

开放/封闭原则是个好主意吗?

这个问题不是关于OCP是什么.我也不是在寻找简单的答案.

所以,这就是我问这个的原因.OCP最初是在80年代后期描述的.它反映了当时的思想和背景.令人担忧的是,在代码已经过测试并投入生产之后,更改源代码以添加或修改功能将最终变得风险太大且成本高昂.因此,我们的想法是尽可能避免更改现有的源文件,并且只以子类(扩展)的形式添加到代码库中.

我可能错了,但我的印象是基于网络的版本控制系统(VCS)当时并未广泛使用.关键是VCS对于管理源代码更改至关重要.

重构的想法是最近的.那些支持自动重构操作的复杂IDE当然不存在.即使在今天,许多开发人员也没有使用最好的重构工具.这里的要点是,这样的现代工具允许开发人员在几秒钟内安全地改变数千行代码.

最后,今天,自动化开发人员测试(单元/集成测试)的想法很普遍.有许多免费和复杂的工具支持它.但是,如果我们从不/很少更改现有代码,那么创建和维护大型自动化测试套件有什么用?正如OCP所要求的那样,新代码只需要新的测试.

那么,OCP今天真的有意义吗?我不这么认为.相反,如果新功能不需要新类,我确实更愿意在添加新功能时更改现有代码.这样做可以使代码库更简单,更小,更易于阅读和理解.破坏以前功能的风险将通过VCS,重构工具和自动化测试套件进行管理.

open-closed-principle

11
推荐指数
2
解决办法
2526
查看次数

理解开放封闭原则

当我遇到以下代码时,我正在重构一个简单的脚本文件解析器的旧代码:

StringReader reader = new StringReader(scriptTextToProcess);
StringBuilder scope = new StringBuilder();
string line = reader.ReadLine();
while (line != null)
{
    switch (line[0])
    {
        case '$':
            // Process the entire "line" as a variable, 
            // i.e. add it to a collection of KeyValuePair.
            AddToVariables(line);
            break;
        case '!':
            // Depending of what comes after the '!' character, 
            // process the entire "scope" and/or the command in "line".
            if (line == "!execute")
                ExecuteScope(scope);
            else if (line.StartsWith("!custom_command"))
                RunCustomCommand(line, scope);
            else if …
Run Code Online (Sandbox Code Playgroud)

c# parsing open-closed-principle

11
推荐指数
1
解决办法
4345
查看次数