Questions tagged «object-oriented-design»

面向对象的设计是规划用于解决软件问题的交互对象系统的过程。

3
在实践中如何遵守开闭原则
我了解开放原则的意图。这是通过告诉您尝试在不进行修改的情况下进行扩展,以降低破坏已在修改过程中起作用的内容的风险。 但是,我在理解此原理在实践中的应用时遇到了一些麻烦。据我了解,有两种方法可以应用它。在可能的更改之前和之后: 之前:编程抽象并尽可能“预测未来”。例如,drive(Car car)如果将来将Motorcycles添加到系统中,则必须更改 方法,因此它可能违反了OCP。但是该方法drive(MotorVehicle vehicle)将来不太可能需要更改,因此它遵循OCP。 但是,很难预测未来并提前知道将对系统进行哪些更改。 之后:需要更改时,扩展类而不是修改其当前代码。 练习1并不难理解。但是,在实践2中,我很难理解如何申请。 例如(我从YouTube视频中获取了它):假设我们在类中有一个接受CreditCard对象的方法:makePayment(CraditCard card)。将一天Voucher添加到系统中。此方法不支持它们,因此必须对其进行修改。 首先实现该方法时,我们无法预测未来,无法以更抽象的术语进行编程(例如makePayment(Payment pay),因此现在我们必须更改现有代码。 练习2说,我们应该通过扩展而不是修改来添加功能。这意味着什么?我应该继承现有的类而不是简单地更改现有的代码吗?我是否应该围绕它进行某种包装,以避免重写代码? 还是该原则甚至不涉及“如何正确修改/添加功能”,而是涉及“如何避免必须首先进行更改(即从程序到抽象)”?

8
技术面试中与OO设计相关的问题[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 4年前关闭。 我最近参加了很多访谈,并且公司要求他们多次回答“设计[插入模型]”问题。 如今,这在行业中很正常吗?我进入软件界已有二十多年了,参加了我的部分采访,但是我看到这种采访模式只是在最近才出现。 我觉得这个问题很开放。例如:我被要求绘制一个类图以“设计停车场”。我不确定面试官期望的详细程度。这是在网上测试中,我应该附上一个visio图,所以我不能问他们对他们的期望是什么。 您是否在面试过程中使用了这类问题?它们仅与类图相关,还是您还询问顺序,流程图和ERD(当然取决于职位的性质),它们在招聘过程中是否有效? *编辑凯文的回应* 例如:一个完整​​的问题可能是“设计可用于查找空位的停车场管理系统” 我可以用2班来完成,ParkingLot而Slot我也可以继续添加IVehicle和Vehicle及Car和Motorcycle类。我在哪里划界线? public class ParkingLot { IVehicle Vehicle {set; get;} List<Slot> GetEmptySlots() { }; } public class Vehicle : IVehicle { Slot SlotNum {set; get;} } public class Slot { int Row {set; get;} int Column {set; get; } }

2
设计:对象方法与以对象为参数的单独类的方法?
例如,这样做更好吗? Pdf pdf = new Pdf(); pdf.Print(); 要么: Pdf pdf = new Pdf(); PdfPrinter printer = new PdfPrinter(); printer.Print(pdf); 另一个例子: Country m = new Country("Mexico"); double ratio = m.GetDebtToGDPRatio(); 要么: Country m = new Country("Mexico"); Country us = new Country("US"); DebtStatistics ds = new DebtStatistics(); double usRatio = ds.GetDebtToGDPRatio(us); double …

2
堆栈扩展LinkedList。是否违反了Liskov替代原则?
存在具有诸如add_first(),add_last(),add_after(),remove_first(),remove_last()和remove()之类的函数的LinkedList类。 现在有一个Stack类,提供了push(),pop(),peek()或top()等功能,并且为了实现这些方法,它扩展了LinkedList类方法。这是否违反了《里斯科夫替代原则》? 例如,考虑在add_after()情况下将节点添加到链接列表的第n个位置的情况。这可以在基类中完成,但不能在Stack类中完成。此处的后置条件是否已减弱,或者您是否修改add_after()方法以将其添加到堆栈顶部? 另外,如果不违反,这是不好的设计吗?以及如何使用LinkedList类实现Stack功能?


5
为什么静态方法不能被重写?
在回答这个问题时,普遍的共识是静态方法不应被覆盖(因此C#中的静态函数不能是虚拟的或抽象的)。但是,不仅在C#中是这种情况。Java也禁止这样做,C ++也似乎不喜欢它。但是,我可以想到许多我想在子类中覆盖的静态函数示例(例如,工厂方法)。从理论上讲,有多种方法可以解决这些问题,但都不是干净或简单的方法。 为什么静态函数不应该被覆盖?

1
对象生存期不变性与移动语义
很久以前,当我学习C ++时,我就强烈强调C ++的部分意思是就像循环具有“循环不变式”一样,类也具有与对象生命周期相关的不变式-应该是正确的只要物体还活着 应该由构造函数建立并由方法保留的事物。封装/访问控制可帮助您强制执行不变式。RAII是您可以使用此想法做的一件事。 从C ++ 11开始,我们现在有了移动语义。对于支持移动的类,从某个对象移动不会正式终止其生命周期,因为该移动应该使它处于某种“有效”状态。 在设计一个类时,如果将其设计为仅保留该类的不变性直到将其移出之前,是不好的做法吗?或者是说没关系,如果它可以让你让它走得更快。 具体来说,假设我有一个不可复制但可移动的资源类型,如下所示: class opaque { opaque(const opaque &) = delete; public: opaque(opaque &&); ... void mysterious(); void mysterious(int); void mysterious(std::vector<std::string>); }; 无论出于何种原因,我都需要为此对象创建一个可复制的包装,以便可以在某些现有的调度系统中使用它。 class copyable_opaque { std::shared_ptr<opaque> o_; copyable_opaque() = delete; public: explicit copyable_opaque(opaque _o) : o_(std::make_shared<opaque>(std::move(_o))) {} void operator()() { o_->mysterious(); } void …

4
将共享数据封装在软件管道中的良好实施策略
我正在努力重构现有Web服务的某些方面。实现服务API的方式是通过具有一种“处理管道”,其中有按顺序执行的任务。毫不奇怪,以后的任务可能需要由以前的任务计算的信息,当前完成此操作的方法是将字段添加到“管道状态”类中。 我一直在思考(并希望?),比在管道步骤之间共享信息的更好方法要好于拥有一个具有成千上万个字段的数据对象,其中某些字段对某些处理步骤有意义,而对另一些处理步骤却没有意义。使该类成为线程安全类将是一个巨大的痛苦(我不知道它是否可能实现),无法推断其不变性(很可能没有任何原因)。 我翻阅了《四人帮》设计模式书以找到一些灵感,但我觉得那儿没有解决的办法(Memento的想法有些相同,但不完全相同)。我也在网上看过,但是第二次搜索“管道”或“工作流”时,您就会被Unix管道信息或专有工作流引擎和框架所淹没。 我的问题是-您将如何处理记录软件处理管道执行状态的问题,以便以后的任务可以使用以前的任务计算的信息?我猜想与Unix管道的主要区别在于,您不仅在乎前一项任务的输出。 根据要求,使用一些伪代码来说明我的用例: “管道上下文”对象具有许多字段,不同的管道步骤可以填充/读取这些字段: public class PipelineCtx { ... // fields public Foo getFoo() { return this.foo; } public void setFoo(Foo aFoo) { this.foo = aFoo; } public Bar getBar() { return this.bar; } public void setBar(Bar aBar) { this.bar = aBar; } ... // more methods } …

7
设计:回调到父类
在使用子对象对对象进行建模时,通常通过合成将子对象包括在内,作为父类的成员。但是有时候孩子需要告诉父母一些事情,他们需要调用父母的函数。使用C ++如何做到这一点?一些选项是: 使父类成为全局类,因此子对象将能够调用父对象的成员函数。 将父对象作为指针或引用注入到每个子对象中。然后,当子项需要告诉父对象某些内容时,它总是可以这样做,因为它具有可以使用的成员变量。 还有什么其他方法可以做到这一点?这种事情是否有通用的设计模式或名称? 请注意,我对C ++中的想法和解决方案感兴趣,因为在其他面向对象的语言中,细节将有所不同。例如,上面的第2点提到了“指针或引用”,并且两者都只能在C ++中使用。C ++具有其他语言没有的语言功能,因此解决该问题的方法的实现可能会合并这些语言功能,从而使该解决方案与某人使用另一种语言可能提出的解决方案有所不同。

2
在DDD中,域服务是否本质上仅仅是门面和/或中介模式?
在域驱动设计中,域层可以具有多个(传统)服务。例如,对于用户域,我们可能有: 一个UserFactory,它以不同的方式构建User对象 一个用户存储库,负责与基础结构层中的持久性服务进行交互 域层中的UserService是仅仅是这两个服务和基础结构层的中介者和/或Facade,还是它还有更多内容?

2
当应用的某些部分用不同的语言编写时,如何避免数据结构重复?
例如,假设您正在用Java编写应用程序。 您的应用程序与使用Python编写的API服务器进行通信。 Python服务器与SQL数据库进行通信。 您还拥有一个用JavaScript编写的应用程序网站。 使用4种不同的语言,很容易以4次不同的时间重复基本相同的数据结构。 例如,User类型可能看起来像这样(伪代码): type User { integer id; string name; timestamp birthday; } 项目的每个部分都需要某种形式的表示User。Java和Python部分将需要两个不同的class声明。数据库将需要一个User表声明。前端站点也需要代表一个站点User。 重复此类型4次确实违反了“ 请勿重复自己”原则。还有一个问题是,如果User更改了类型,则需要在项目的每个不同部分中重复这些更改。 我知道Google的protobuf库为该问题提供了一种解决方案,您可以使用特殊的语法编写数据结构,然后该库以多种不同的编程语言为您生成结构声明。但这仍然没有解决必须为您的类型重复验证逻辑的问题。 是否有人对此有任何建议或链接到书籍/博客文章?

2
如何真正找出面向对象设计中必须要做的事情?
首先免责声明:我真的不知道这个问题是否适合该网站,但是我仍然发现它不仅对我而且对其他初学者都是一个相关的问题。如果可以改善问题以使其适合此处,请指出int注释。如果不合适,也让我知道,如果可能的话,让我知道可以在哪里讨论,因为我没有找到任何好的论坛。 我在2009年学习PHP时就学会了编程。2012年晚些时候,我转到了C#和.NET。无论如何,编码不是问题,写下算法不是我的问题。我的实际问题是要知道必须编码什么才能达到要求,必须在哪里编码。 网络上提供的大多数课程都讨论了如何 -如何用某种语言编写代码,如何使用一些API集等。这不是我的意思。 这些年来,我读了很多有关一堆东西的信息:面向对象的分析和设计,设计模式,领域驱动的设计等等。例如,我了解SOLID原则,DDD的一些主要思想,例如聘请领域专家的必要性,开发无处不在的语言等。我敢说我的理论背景至少合理。 但是,当谈到练习时,我觉得自己是一场灾难。前一段时间,我需要继续开发已经由其他人开发的金融系统。这就是用C#和WinForms开发的那种“旧系统”。这是我第一次选择一个具有实际领域复杂性,业务规则等等的项目。 我承认,当我大多数时候收到要求时,我认为“这到底是怎么做的?” -我什至不知道如何开始着手研究需求以弄清楚必须做什么。我认为我的主要困惑是我必须编写什么代码,什么类,接口以及每条逻辑的去向,每件事必须在哪个类上。问题是我不知道从哪里开始。 大多数时候,经过很多思考,我最终想到了一些主意,但是我却永远不知道如何判断我的主意是否正确。 我的意思是我不认为这是一种理论上的不足,因为我说我已经阅读了有关软件体系结构和面向对象的一堆建议,但对确定实践中必须做的工作并没有多大帮助。 所以,我怎么能学会真正 做到面向对象的设计?我要学习的是:给定的需求知道如何开始在一个过程中进行工作,从而找出必须完成的工作以及每个代码所属的位置。我还如何学习判断我的想法是否正确? 我相信在这里不可能完全解释这一点作为答案。但是,我所寻找的可能是根据网站样式而定的答案,只是给出概述并指出一些参考资料(书籍,在线课程等),这些参考资料可用于扩展思想并真正学习这些知识。

5
如何避免在管理缓存的类中违反SRP?
注意:代码示例是用c#编写的,但这无关紧要。我将c#用作标签,因为找不到更合适的标签。这是关于代码结构的。 我正在阅读Clean Code,并试图成为一个更好的程序员。 我经常发现自己难以遵循“单一责任原则”(类和功能只能做一件事),尤其是在功能方面。也许我的问题是“一件事”的定义不明确,但仍然... 一个例子:我在数据库中有一个Fluffies列表。我们不在乎什么是蓬松。我想上课恢复蓬松。但是,蓬松可以根据某些逻辑进行更改。根据某些逻辑,此类将从缓存中返回数据或从数据库中获取最新数据。我们可以说它管理蓬松,这是一回事。为了简单起见,假设加载的数据可以使用一个小时,然后必须重新加载。 class FluffiesManager { private Fluffies m_Cache; private DateTime m_NextReload = DateTime.MinValue; // ... public Fluffies GetFluffies() { if (NeedsReload()) LoadFluffies(); return m_Cache; } private NeedsReload() { return (m_NextReload < DateTime.Now); } private void LoadFluffies() { GetFluffiesFromDb(); UpdateNextLoad(); } private void UpdateNextLoad() { m_NextReload = DatTime.Now …


4
处理模型和视图时切换与多态
我想不出更好的解决方案。我有一个显示元素列表的视图控制器。这些元素是可以作为B,C,D等的实例并从A继承的模型。因此,在该视图控制器中,每个项目都应转到应用程序的不同屏幕,并在用户选择其中的一个时传递一些数据。 。我想到的两个选择是(请忽略语法,它不是特定的语言) 1)开关(我知道那很烂) //inside the view controller void onClickItem(int index) { A a = items.get(index); switch(a.type) { case b: B b = (B)a; go to screen X; x.v1 = b.v1; // fill X with b data x.v2 = b.v2; case c: go to screen Y; etc... } } 2)多态 //inside …

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.