Questions tagged «object-oriented-design»

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

10
我们可以没有构造函数吗?
假设出于某种原因,所有对象都是通过$ obj = CLASS :: getInstance()创建的。然后,我们使用setter注入依赖项,并使用$ obj-> initInstance();开始初始化。如果我们根本不使用构造函数,是否有无法解决的实际麻烦或情况? ps用这种方法创建对象的原因是,我们可以根据一些规则替换getInstance()中的类。 我在用PHP工作,如果那件事


12
面向对象设计
假设您具有以下条件: +--------+ +------+ | Animal | | Food | +-+------+ +----+-+ ^ ^ | | | | +------+ +-------+ | Deer | | Grass | +------+ +-------+ Deer从继承Animal和Grass继承Food。 到目前为止,一切都很好。Animal物体可以吃Food物体。 现在,让它混合一点。让我们添加一个Lion继承自的Animal。 +--------+ +------+ | Animal | | Food | +-+-----++ +----+-+ ^ ^ ^ | | | | | | +------+ …

6
对象应该知道自己的ID吗?
obj.id似乎相当普遍,似乎也落入了对象可能了解的自身范围之内。我发现自己在问为什么我的对象应该知道自己的ID? 它似乎没有理由拥有它吗?存在它的主要原因之一是检索它,因此我的存储库需要知道它,然后将其用于数据库交互。 我还曾经遇到一个问题,我想将对象序列化为RESTful API的JSON,其中id似乎不适合有效负载,但是仅URI并将其包含在对象中使事情变得更加困难。 对象应该知道它自己的ID吗?为什么或者为什么不? 更新: 条款 id:对象的标识符属性。用数据库术语来说,代理键不是自然键。 对象:系统中的实体或其他可唯一标识的对象。

4
使用C#中的抽象类作为定义
作为一名C ++开发人员,我已经习惯了C ++头文件,并发现在代码中包含某种强制性的“文档”很有用。通常,在这种情况下,我不得不读一些C#代码时会很糟糕:我没有正在使用的类的思维导图。 假设作为软件工程师,我正在设计程序的框架。将每个类都定义为抽象的未实现类是否太疯狂了,就像我们对C ++标头所做的那样,让开发人员实现它呢? 我猜可能有人可能会因为某些原因而认为这是一个糟糕的解决方案,但我不确定为什么。这样的解决方案必须考虑什么?



3
具有共同功能的Windows窗体的最佳设计
过去,我使用继承来允许在应用程序中扩展Windows窗体。如果我所有的表单都具有公共控件,插图和功能,那么我将创建一个实现公共控件和功能的基本表单,然后允许其他控件从该基本表单继承。但是,我在设计时遇到了一些问题。 控件一次只能放在一个容器中,因此您拥有的任何静态控件都将很棘手。例如:假设您有一个称为BaseForm的基本表单,其中包含一个TreeView,并对其进行了保护和静态处理,以便此类的所有其他(派生)实例都可以修改和显示相同的TreeView。这对于从BaseForm继承的多个类不起作用,因为TreeView一次只能位于一个容器中。它可能在初始化的最后一个表单上。尽管每个实例都可以编辑该控件,但在给定时间只能显示一个。当然,有一些变通方法,但是它们都很丑陋。(这对我来说似乎是一个非常糟糕的设计。为什么多个容器不能存储指向同一对象的指针?无论如何,它就是它。) 表单之间的状态,即按钮状态,标签文本等,我必须使用全局变量并在Load上重置状态。 Visual Studio的设计师并不能很好地支持此功能。 是否有更好但仍易于维护的设计可供使用?还是形式继承仍然是最好的方法? 更新 从查看MVC到MVP,从观察者模式到事件模式。这是我目前的想法,请批评: 我的BaseForm类将仅包含控件以及与这些控件相关的事件。需要任何逻辑来处理它们的所有事件都将立即传递给BaseFormPresenter类。此类将处理来自UI的数据,执行任何逻辑操作,然后更新BaseFormModel。该模型会将事件(状态更改时将触发)的事件公开给Presenter类,该类将订阅(或观察)该事件。演示者收到事件通知后,它将执行任何逻辑,然后演示者将相应地修改视图。 内存中每个Model类只有一个,但是可能存在许多BaseForm实例,因此有BaseFormPresenter。这将解决我将BaseForm的每个实例同步到相同数据模型的问题。 问题: 哪一层应该存储最后按下的按钮之类的内容,以便我可以在表单之间为用户(例如CSS菜单中)突出显示它? 请批评这个设计。谢谢你的帮助!

3
永远不要让公众成员虚拟/抽象-是吗?
早在2000年代,我的一位同事就告诉我,将公共方法虚拟化或抽象化是一种反模式。 例如,他认为这样的课程设计得不好: public abstract class PublicAbstractOrVirtual { public abstract void Method1(string argument); public virtual void Method2(string argument) { if (argument == null) throw new ArgumentNullException(nameof(argument)); // default implementation } } 他说 实现Method1并重写的派生类的开发人员Method2必须重复参数验证。 如果基类的开发人员决定在Method1或Method2以后的可自定义部分周围添加一些内容,他将无法执行。 相反,我的同事提出了这种方法: public abstract class ProtectedAbstractOrVirtual { public void Method1(string argument) { if (argument == null) throw new …

9
init()方法有代码味道吗?
声明init()类型的方法是否有目的? 我不是问我们是否应该优先init()于构造函数,或者如何避免声明init()。 我问的是在声明方法(查看它的普遍性)后是否有任何理论依据,init()或者它是否是一种代码味道,应避免使用。 这个init()习语很普遍,但是我还没有看到任何真正的好处。 我说的是鼓励通过方法初始化的类型: class Demo { public void init() { //... } } 什么时候可以在生产代码中使用它? 我觉得这可能是代码的味道,因为它表明构造函数未完全初始化对象,从而导致部分创建了对象。如果未设置状态,则该对象不应存在。 从企业应用的意义上讲,这使我相信它可能是某种用于加速生产的技术的一部分。这是我可以想到的惯用法,这是唯一合乎逻辑的原因,但我不确定是否会有这样的习惯。


4
如何在关系数据库驱动的应用程序中设计不好的数据库中创建更好的OO代码
我正在编写一个Java Web应用程序,该应用程序主要由一堆相似的页面组成,其中每个页面都有多个表和一个适用于这些表的过滤器。这些表上的数据来自SQL数据库。 我将myBatis用作ORM,在我的情况下,这可能不是最佳选择,因为数据库设计不良,而mybatis是面向数据库的工具。 我发现我正在编写很多重复的代码,因为由于数据库的不良设计,我不得不为类似的事情编写不同的查询,因为这些查询可能非常不同。也就是说,我无法轻松地将查询参数化。这会传播到我的代码中,而不是通过一个简单的循环来填充表中列上的行,我将代码改为: 得到一个数据(p1,...,pi); 得到B数据(p1,...,pi); 获得C数据(p1,...,pi); 获得D数据(p1,...,pi); ... 当我们有带有不同列的不同表时,这很快就会爆炸。 这也增加了我使用“ wicket”的复杂性,实际上是将对象映射到页面中的html元素。因此,我的Java代码成为了数据库和前端之间的适配器,这使我创建了许多布线,样板代码,并在其中混入了一些逻辑。 正确的解决方案是在ORM映射器上包裹一个额外层,该额外层为db提供一个更均匀的接口,还是有更好的方法来处理我正在编写的这些意大利面条式代码? 编辑:有关数据库的更多信息 该数据库主要保存电话信息。较差的设计包括: 具有人工ID作为主键的表与域知识无关。 没有唯一,触发器,检查或外键。 具有通用名称的字段,这些字段匹配不同记录的不同概念。 只能通过与其他具有不同条件的表交叉才能分类的记录。 应为数字或日期存储为字符串的列。 综上所述,到处都是凌乱/懒惰的设计。

7
C程序的OO最佳实践
已关闭。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅通过编辑此帖子来关注一个问题。 4年前关闭。 “如果您真的想要OO糖-请使用C ++” –当我问到这一点时,我立即从我的一位朋友那里得到了答复。我知道这里有两件事是完全错误的。首先,OO不是“糖”,其次,C ++没有吸收C。 我们需要用C语言编写服务器(前端将使用Python),因此我正在探索更好的方法来管理大型C程序。 根据对象和对象交互对大型系统进行建模,使其更具可管理性,可维护性和可扩展性。但是,当您尝试将此模型转换为不包含对象(及其所有其他对象)的C语言时,您将面临一些重要的决策。 您是否创建了自定义库来提供系统所需的OO抽象?诸如对象,封装,继承,多态性,异常,发布/订阅(事件/信号),名称空间,自省等(例如GObject或COS)。 或者,您仅使用基本的C构造(struct和函数)以即席方式近似所有对象类(和其他抽象)。(例如,关于SO的此问题的一些答案) 第一种方法为您提供了一种结构化的方法,用于在C中实现整个模型。但是,这也增加了您必须维护的复杂性。(请记住,首先要通过使用对象来减少复杂性)。 我不知道第二种方法,以及它在逼近您可能需要的所有抽象方面的效果如何。 因此,我的简单问题是:在C语言中实现面向对象设计的最佳实践是什么。记住,我并不是在问如何做到这一点。这个和这个问题都在谈论,甚至有一本书。我更感兴趣的是一些现实的建议/示例,这些示例/示例解决了此问题时出现的实际问题。 注意:请不要建议为什么不应该使用C来支持C ++。我们已经超越了那个阶段。

1
为什么(/ did)Bertrand Meyer认为子类化是扩展“封闭式”模块的唯一方法?
在Meyer的“ 面向对象的软件构造”(1988)中,他将开放/封闭原则定义如下: 如果模块仍可扩展,则称其为打开状态。例如,应该可以向其包含的数据结构添加字段,或者向其执行的功能集添加新元素。 如果某个模块可供其他模块使用,则将其称为已关闭。假设已为模块提供了良好定义的稳定描述(信息隐藏的界面)。 他接着说: 如果重新打开模块,则还必须重新打开其所有客户端以对其进行更新,因为它们依赖于旧版本。…[此问题]每当模块必须由新功能或数据元素扩展时触发,从而触发直接和间接客户端中的更改。...使用经典的设计和编程方法,无法编写打开和关闭的模块。 Meyer解决这个难题的方法是:永远不要通过修改现有的类来扩展库模块;而是编写一个新模块来对现有类进行子类化,并使新客户端依赖于该新模块。 现在,在1988年,我正在用Turbo Pascal和Blankenship Basic编写玩具(程序)程序,而我在21世纪的专业经验是使用JVM,CLR和动态语言,所以我不知道Meyer的意思。通过“经典的设计和编程方法”。 Meyer的一个具体示例说明了为什么必须重新打开客户端模块(枚举上的switch语句,现在有更多的成员,需要更多的情况)似乎很合理,但是他几乎没有断言每次向库添加功能时都会断言模块,您需要更新其所有客户端。 是否有历史原因使该主张在1988年显得不言而喻?例如,向C静态库添加函数或数据结构是否更改了布局,以至于即使使用向后兼容的API,也必须重新编译客户端?还是Meyer真的只是在谈论一种用于强制API向后兼容的机制?

7
我应该为数据传输对象创建接口吗?
为数据传输对象创建接口是一个好主意还是一个坏主意?假定对象通常是可变的。 尽管我的示例是使用Java编写的,但它应适用于具有类似概念的任何其他语言。 interface DataTransferObject { String getName(); void setName(String name); } class RealDataTransferObject implements DataTransferObject { String name; String getName() { return name; } void setName(String name) { this.name = name; } } 当然,这是一个简化的示例,在现实生活中可能会有更多的领域。

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.