Questions tagged «object-oriented»

一种使系统能够建模为一组对象的方法论,这些对象可以模块化方式进行控制和操作

4
用OO语言编写逻辑过程软件的最简洁方法
我是一名电气工程师,我不知道自己在做什么。请保存我的代码的未来维护者。 最近,我一直在研究一些较小的程序(在C#中),其功能在逻辑上是“过程的”。例如,其中之一是一个程序,该程序从不同的数据库收集信息,使用该信息生成某种摘要页面,将其打印出来,然后退出。 所有这些所需的逻辑约为2000行。我当然不想像以前的开发人员所做的那样将所有内容全部填充到一起main(),然后用来“清理” #region(颤抖)。 这是我已经尝试过但不太满意的一些事情: 为每个粗略的功能(例如DatabaseInfoGetter,SummaryPageGenerator和PrintUtility)创建静态实用程序。使主要功能看起来像: int main() { var thisThing = DatabaseInfoGetter.GetThis(); var thatThing = DatabaseInfoGetter.GetThat(); var summary = SummaryPageGenerator.GeneratePage(thisThing, thatThing); PrintUtility.Print(summary); } 对于一个程序,我什至使用了接口 int main() { /* pardon the psuedocode */ List<Function> toDoList = new List<Function>(); toDoList.Add(new DatabaseInfoGetter(serverUrl)); toDoList.Add(new SummaryPageGenerator()); toDoList.Add(new PrintUtility()); foreach (Function f in toDoList) f.Do(); …

5
当将数据而不是方法参数传递给构造函数时,类的概念如何改变?
假设我们正在做一个解析器。一种实现可以是: public sealed class Parser1 { public string Parse(string text) { ... } } 或者我们可以将文本传递给构造函数: public sealed class Parser2 { public Parser2(string text) { this.text = text; } public string Parse() { ... } } 在两种情况下用法都很简单,但是与另一种相比,启用向的参数输入是什么意思Parser1?当他们查看API时,我向同一个程序员发送了什么消息?此外,在某些情况下是否存在任何技术优势/劣势? 当我意识到接口在第二种实现中将变得毫无意义时,又出现了另一个问题: public interface IParser { string Parse(); } ...第一个接口上的接口至少可以达到某些目的。这是否特别表示某类是“可接口的”?

7
在面向对象的语言中,对象应何时对自己进行操作,何时应对对象进行操作?
假设有一个Page类,它表示对页面渲染器的一组指令。假设有一个Renderer知道如何在屏幕上呈现页面的类。可以通过两种不同的方式来构造代码: /* * 1) Page Uses Renderer internally, * or receives it explicitly */ $page->renderMe(); $page->renderMe($renderer); /* * 2) Page is passed to Renderer */ $renderer->renderPage($page); 每种方法的优缺点是什么?什么时候会更好?什么时候会更好? 背景 为了增加一些背景知识-我发现自己在同一代码中同时使用了这两种方法。我正在使用名为的第三方PDF库TCPDF。在我的代码中的某些地方,必须具备以下条件才能使PDF呈现工作: $pdf = new TCPDF(); $html = "some text"; $pdf->writeHTML($html); 假设我希望创建页面的表示形式。我可以创建一个模板,其中包含用于呈现PDF页面摘要的说明,如下所示: /* * A representation of the PDF page snippet: * a …

2
我们真的可以在OOP中使用不变性而不丢失所有关键的OOP功能吗?
我看到了使程序中的对象不变的好处。当我真正地为自己的应用程序考虑一个好的设计时,我常常自然而然地想到我的许多对象都是不可变的。我常常想让所有对象保持不变。 这个问题涉及相同的想法,但没有答案表明什么是不变性的好方法以及何时实际使用它。是否有一些好的不变设计模式?总体思路似乎是“使对象不可变,除非您绝对需要更改它们”,这在实践中毫无用处。 我的经验是,不变性将我的代码越来越多地驱动到功能范式,并且这种发展总是会发生: 我开始需要持久性(在功能上)数据结构,例如列表,地图等。 使用交叉引用非常不方便(例如,树节点引用其子节点,而子节点引用其父节点),这使我根本不使用交叉引用,这又使我的数据结构和代码更具功能性。 继承不再有任何意义,我开始改用合成。 OOP的整个基本概念(如封装)开始瓦解,而我的对象开始看起来像函数。 在这一点上,我几乎不再使用OOP范例中的任何内容,而可以切换到纯函数式语言。因此,我的问题是:是否有一种一致的方法来进行良好的不可变OOP设计,或者总是总是这样,当您将不可变的想法发挥到最大潜力时,您总是最终会使用一种功能语言进行编程,而该语言不再需要OOP世界中的任何东西?是否有任何好的指导方针来决定哪些类应该是不可变的,哪些应该保持可变以确保OOP不会崩溃? 为了方便起见,我将提供一个示例。让我们拥有一个ChessBoard不可变棋子的不可变集合(扩展抽象类)Piece)。从OOP的角度来看,一块负责从板上的位置生成有效的移动。但是要生成移动,棋子需要引用其棋盘,而棋盘需要引用其棋盘。好了,有一些技巧可以根据您的OOP语言创建这些不可变的交叉引用,但是它们很难管理,最好不要用它来引用其董事会。但是由于不知道棋盘的状态,所以棋子无法产生移动。然后,片段变成仅包含片段类型及其位置的数据结构。然后,您可以使用多态函数来生成各种片段的移动。这在函数式编程中是完全可以实现的,但是如果没有运行时类型检查和其他不良的OOP惯例,在OOP中几乎是不可能的...然后,

6
在非OO中如何编程?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 2年前关闭。 在阅读有关OOP缺点的严厉文章以支持其他一些范例的过程中,我遇到了一个例子,我发现它没有太多的缺点。 我想对作者的论点持开放态度,尽管我从理论上可以理解他们的观点,但尤其是一个例子,我很难想象如何用FP语言更好地实现它。 来自:http : //www.smashcompany.com/technology/object-oriented-programming-is-an-expensive-disaster-which-must-end // Consider the case where “SimpleProductManager” is a child of // “ProductManager”: public class SimpleProductManager implements ProductManager { private List products; public List getProducts() { return products; } public void increasePrice(int percentage) { if (products != null) { for (Product product : …

5
有什么好的设计习惯可以避免询问子类类型?
我已经读到,当您的程序需要知道对象是什么类时,通常表明存在设计缺陷,因此我想知道什么是处理此问题的好方法。我正在实现一个Shape类,该类具有从其继承的不同子类,例如Circle,Polygon或Rectangle,并且我有不同的算法来确定Circle是否与Polygon或Rectangle碰撞。然后假设我们有两个Shape实例,并且想知道一个是否与另一个碰撞,在这种方法中,我必须推断正在碰撞的对象是哪种子类类型,以便知道应该调用哪种算法,但这是一个设计或实践不当?这就是我解决的方法。 abstract class Shape { ShapeType getType(); bool collide(Shape other); } class Circle : Shape { getType() { return Type.Circle; } bool collide(Shape other) { if(other.getType() == Type.Rect) { collideCircleRect(this, (Rect) other); } else if(other.getType() == Type.Polygon) { collideCirclePolygon(this, (Polygon) other); } } } 这是一种不良的设计模式吗?如何解决这个问题而不必推断子类类型?

7
用OO语言实现对象状态?
我已经看过一些Java代码,它可以模拟赛车,其中包括基本状态机的实现。这不是经典的计算机科学状态机,而仅仅是一个可以具有多个状态并且可以基于一系列计算在其状态之间进行切换的对象。 为了描述问题,我有一个Car类,它带有一个嵌套的枚举类,该类为汽车的状态定义了一些常量(例如OFF,IDLE,DRIVE,REVERSE等)。在同一个Car类中,我有一个update函数,该函数基本上由一个大的switch语句组成,该语句打开汽车的当前状态,进行一些计算,然后更改汽车的状态。 据我所知,Cars状态仅在其自己的类中使用。 我的问题是,这是处理上述性质的状态机的最佳方法吗?听起来确实是最明显的解决方案,但过去我一直听说“ switch语句不好”。 我在这里看到的主要问题是,随着我们添加更多状态(如果认为必要),switch语句可能会变得非常大,并且代码可能变得笨拙且难以维护。 有什么更好的解决方案?

3
应该如何设计“员工”类?
我正在尝试创建一个用于管理员工的程序。但是,我无法弄清楚如何设计Employee课程。我的目标是能够使用Employee对象在数据库上创建和操作员工数据。 我想到的基本实现就是这样一个简单的实现: class Employee { // Employee data (let's say, dozens of properties). Employee() {} Create() {} Update() {} Delete() {} } 使用此实现,我遇到了几个问题。 该ID雇员是由数据库给出的,所以如果我使用描述的新雇员的对象,不会有ID存储然而,当代表现有员工的对象将有一个ID。因此,我有一个属性,它有时描述对象,有时却不描述(这可能表明我们违反了SRP?因为我们使用同一类来表示新员工和现有员工...)。 该Create方法应该在数据库上创建一个雇员,而Update和Delete应该作用于现有雇员(再次,SRP ...)。 “创建”方法应具有哪些参数?所有员工数据或Employee对象的数十个参数? 班级应该是一成不变的吗? 会如何Update工作?是否需要属性并更新数据库?还是需要两个对象-一个“旧”对象和一个“新”对象,并使用它们之间的差异更新数据库?(我认为答案与该类的可变性有关)。 建设者的责任是什么?它需要什么参数?它会使用id参数从数据库中获取员工数据并填充属性吗? 因此,如您所见,我的头有些乱,我非常困惑。您能否帮助我了解此类课程的外观? 请注意,我只是为了了解通常如何设计这种经常使用的类而不想发表意见。

5
向UI报告进度的最佳策略-回调应该如何发生?
有时,用户会启动一项扩展的技术操作,该操作需要一段时间才能执行。在这些情况下,通常最好显示某种进度条以及有关当前正在执行哪个任务的信息。 为了避免UI和逻辑层之间的紧密耦合,通常最好通过某种代理进行通信。也就是说,后端不应该操纵自己的UI元素,甚至不应该直接与中介层进行交互。 显然,必须在某处进行一些回调才能使此工作正常进行。我通常以两种方式之一实现它: 将可变对象传递给后端,并让后端在进行时对其进行更改。发生更改时,对象会通知前端。 传递形式void f(ProgressObject)或后端调用的回调函数ProgressObject -> unit。在这种情况下,后端构造了ProgressObject,并且完全是被动的。我认为,每次要报告进度时,它都必须构造一个新对象。 这些方法的缺点和优点是什么?有没有商定的最佳使用方法?有不同的使用环境吗? 是否有完全不同的报告进度的技术被我忽略了?

2
良好实践中的DRY原则?
我试图在编程中尽可能地遵循DRY原则。最近,我一直在学习OOP中的设计模式,最后又重复了一遍。 我创建了一个Repository模式以及一个Factory模式和Gateway模式来处理我的持久性。我在应用程序中使用数据库,但这没关系,因为如果我愿意,我应该能够换出网关并切换到另一种持久性。 我最终为自己创建的问题是,我为拥有的表数创建了相同的对象。例如,这些将是我需要处理表的对象comments。 class Comment extends Model { protected $id; protected $author; protected $text; protected $date; } class CommentFactory implements iFactory { public function createFrom(array $data) { return new Comment($data); } } class CommentGateway implements iGateway { protected $db; public function __construct(\Database $db) { $this->db = $db; } public function …

2
仅具有一个实例的Python类:何时创建(单个)类实例以及何时使用该类?
给定一个仅实例化一次的Python类,即该类中只有一个对象。我想知道在什么情况下创建单个类实例而不是直接与该类一起工作才有意义。 有一个类似的问题,但重点不同: 它是关于将全局变量和函数分组为一个类, 它不是特定于Python的。后者意味着它不考虑(在Python中)类也是对象的事实。 更新: 在Python中,我可以对类和对象执行以下操作: class A(object): pass A.some_state_var = True # Then later A.some_state_var = False my_a = A() my_a.some_state_var = True # Then later my_a.some_state_var = False 因此,我看不到在类和该类的实例之间进行选择如何与状态有关(在Python中)。我可以通过两者之一来保持状态。 此外,创建我的类/类实例的动机与执行Singleton要求无关。 另外,创建新的Type并不需要太多。 这样做的动机是将相关的代码和数据进行分组,并为其提供接口。这就是为什么我最初在类图中将其建模为类的原因。仅当涉及到实现时,我才开始怀疑是否要实例化此类。

5
在这种情况下,我应该选择组合还是继承?
考虑一个接口: interface IWaveGenerator { SoundWave GenerateWave(double frequency, double lengthInSeconds); } 此接口由许多类实现,这些类生成不同形状的波(例如SineWaveGenerator和SquareWaveGenerator)。 我想实现一个SoundWave基于音乐数据而不是原始声音数据生成类的类。它会收到音符的名称和以拍子(不是秒)为单位的长度,并在内部使用该IWaveGenerator功能来创建一个音符SoundWave。 问题是,应该NoteGenerator包含IWaveGenerator还是应该从IWaveGenerator实现中继承? 由于两个原因,我倾向于合成: 1 -它让我注入任何IWaveGenerator的NoteGenerator动态。另外,我只需要一个NoteGenerator类,而不是SineNoteGenerator,SquareNoteGenerator等等。 2-无需NoteGenerator公开由定义的较低级接口IWaveGenerator。 但是,我发布此问题是为了听取对此的其他意见,也许是我没有想到的要点。 顺便说一句:我会说NoteGenerator 从概念上讲是an,IWaveGenerator因为它生成SoundWaves。

4
“ OOP隐藏状态”是什么意思?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 5年前关闭。 在cat-v.org上的许多反OOP咆哮中,我发现Joe Armstrong的一段话提出了一些反对OOP模型的异议,其中之一是: 异议4 –对象具有私有状态 国家是万恶之源。特别应避免具有副作用的功能。 尽管编程语言中的状态是不可取的,但在现实世界中,状态比比皆是。我对银行帐户的状态非常感兴趣,当我从银行存款或取款时,我希望银行帐户的状态能够正确更新。 考虑到现实中存在状态,编程语言应提供哪些设施来处理状态? OOPL说“隐藏程序员的状态”。状态只能通过访问功能隐藏和看到。常规编程语言(C,Pascal)说,状态变量的可见性由该语言的作用域规则控制。纯声明性语言表示没有状态。系统的全局状态包含在所有功能中,并且来自所有功能。诸如monads(用于FPL)和DCG(逻辑语言)之类的机制用于向程序员隐藏状态,以便它们可以“好像状态无关紧要”进行编程,但在必要时可以完全访问系统状态。 OOPL选择的“从程序员隐藏状态”选项是最糟糕的选择。他们没有揭露状态并试图找到最小化状态滋扰的方法,而是将其隐藏了起来。 这到底是什么意思?我几乎没有底层或程序方面的经验,主要是OOP,所以这可能解释了我对此有多么不熟悉。从更现代的角度来看,现在大多数面向对象的歇斯底里都通过了(至少据我所知),你们认为这种通过的准确性/相关性如何? 谢谢你的帮助。

5
是否应该始终完全封装内部数据结构?
请考虑此类: class ClassA{ private Thing[] things; // stores data // stuff omitted public Thing[] getThings(){ return things; } } 此类将用于存储数据的数组公开给任何感兴趣的客户端代码。 我是在正在开发的应用中完成此操作的。我有一个ChordProgression存储序列Chords的类(并执行其他一些操作)。它有一个Chord[] getChords()返回和弦数组的方法。当必须更改数据结构(从数组更改为ArrayList)时,所有客户端代码都将中断。 这让我思考-也许以下方法更好: class ClassA{ private Thing[] things; // stores data // stuff omitted public Thing[] getThing(int index){ return things[index]; } public int getDataSize(){ return things.length; } public void setThing(int …

6
哪些更改太大而无法通过适当的设计轻松实现?
这是一个相当模糊的问题,但这是我在阅读有关适当设计的内容时从未感到满意的答案。 通常,在学习面向对象的编程,抽象,分解等方法时,设计的圣杯以及它们始终声称您使用的是开发技术的原因是,这将使您的程序“易于更改” ,“可维护的”,“灵活的”或用于表达这种有效果的概念的任何同义词。通过将ivars标记为私有,将代码拆分为许多小的自包含方法,使接口保持通用,可以使您完全轻松自如地修改程序。 对于较小的更改,这对我来说效果很好。改变类以提高性能所用的内部数据结构从来都不是主要困难,而且独立于API的用户界面端也没有改变,例如重新设计文本输入系统或检修游戏元素的图形。 所有这些更改似乎天生就是独立的。就所涉及的外部代码而言,它们均不涉及对要修改的程序组件的行为或设计进行任何更改。无论您是以程序编写还是以OO样式编写(具有大型功能还是小型功能),即使您只有中等程度的设计,也可以轻松进行这些更改。 但是,每当更改变得繁琐而繁琐时(即,对API进行更改),我的所有宝贵“模式”都无法挽救。巨大的变化仍然很大,受影响的代码仍然受到影响,并且大量的错误产生工作摆在我面前。 所以,我的问题是这个。适当的设计声称能够促进多大的变化?是否有一些其他的设计技术,或者对我来说是未知的,或者是我没有实现,确实确实使粘滞性修改变得简单,还是那个承诺(我听说过这么多不同的范例)仅仅是一个好主意,完全脱离了软件开发的一成不变的真理?我可以添加到工具栏中的“更改工具”吗? 具体来说,导致我进入论坛的问题是:我一直在努力实现一种解释性编程语言(在D中实现,但这无关紧要),并且我决定将闭包的参数设为基于关键字,而不是当前的位置。这就需要修改所有现有的调用匿名函数的代码,幸运的是,这很小,因为我很早就开发了我的语言(<2000行),但是如果我稍后再做出决定,那将是巨大的。在这种情况下,是否可以通过适当的预见性设计使修改变得更容易,或者确定(大多数)变化本质上影响深远?我很好奇这是否是我自己的设计技能的失败-如果是的话,我 明确地说,我绝不怀疑OOP或其他常用的模式。但是,对我而言,它们的优点在于代码库的原始编写而不是维护。继承使您可以很好地抽象出重复的模式,多态性使您可以通过人类理解的函数(哪个类)而不是由机器理解的效果(switch语句的哪个分支)来分离代码,而小的独立函数可以让您以一种非常愉快的“自下而上”的风格写作。但是,我对他们的灵活性表示怀疑。

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.