Questions tagged «design-patterns»

设计模式是解决软件设计中常见问题的通用可重用解决方案。

11
多少个设计模式和抽象级别是必需的?[关闭]
我怎样才能知道我的软件有太多的抽象和太多的设计模式,或者反过来,我怎么知道它是否应该有更多的抽象呢? 与我合作的开发人员在这些方面的编程方式有所不同。 有些人确实提取每个小功能,尽可能使用设计模式,并不惜一切代价避免冗余。 其他人,包括我在内,都试图更加务实,并编写出并非完全适合每种设计模式的代码,但由于应用了较少的抽象,因此其理解速度更快。 我知道这是一个权衡。我如何知道何时将足够的抽象放入项目中,又如何知道需要更多抽象呢? 例如,当使用Memcache编写通用缓存层时。难道我们真的需要Memcache,MemcacheAdapter,MemcacheInterface,AbstractCache,CacheFactory,CacheConnector,...,或者这是更易于维护和使用仍然只有一半时,好的代码这些类的? 在Twitter中找到了这个: (https://twitter.com/rawkode/status/875318003306565633)

4
C#6.0的新空条件运算符是否违反Demeter定律?
该德米特法律规定如下: 每个单元对其他单元的知识应该有限:只有与当前单元“紧密”相关的单元。 每个单位只能与朋友交谈;不要和陌生人说话。 只与您的直系朋友交谈。 C#6.0引入了一个称为空条件运算符的新运算符。恕我直言,它使编码更容易并提高了可读性。但这也使编写更多耦合的代码变得更容易,因为更容易在已经检查了无效性的类字段中导航(类似var x = A?.B?.C?.D?.E?.F?)。 陈述这名新操作员违反Demeter法则是否正确?

8
代码和数据的分离如何成为一种惯例?
请仔细阅读问题:它询问的是方式,而不是原因。 我最近遇到了这个答案,它建议使用数据库存储不可变数据: 听起来您描述的许多魔术数字(尤其是如果它们是部分依赖的)实际上是数据,而不是代码。[...]它可能意味着一个SQL类型的数据库,或者可能只是意味着一个格式化的文本文件。 在我看来,如果您的数据属于程序的一部分,那么要做的就是将其放入程序中。例如,如果您程序的功能是计算元音,那么里面有什么问题vowels = "aeiou"呢?毕竟,大多数语言都具有专门为此目的设计的数据结构。您为什么要麻烦将数据放入“格式化的文本文件”中来分离数据,如上所述?为什么不只使用您选择的编程语言来格式化该文本文件?现在是数据库吗?还是代码? 我敢肯定,有些人会认为这是一个愚蠢的问题,但我会严肃地问这个问题。我觉得“分开的代码和数据”在文化上正在逐渐成为一种不言而喻的真理,以及诸如“不要给变量带来误导性的名称”和“不要仅因为您的语言考虑而使用空格”之类的显而易见的事情。无关紧要”。 例如,这篇文章:从P代码中分离数据的问题。有问题吗?什么问题?如果Puppet是用于描述我的基础结构的语言,为什么它不能还描述名称服务器是8.8.8.8?在我看来,问题不在于代码和数据混杂在一起,1而是Puppet缺乏足够丰富的数据结构和与其他事物交互的方式。 我发现这种转变令人不安。面向对象的编程说“我们想要任意丰富的数据结构”,因此赋予数据结构以代码的能力。结果就是封装和抽象。甚至SQL数据库都有存储过程。当您将数据隔离到YAML或文本文件或哑数据库中时,就好像要从代码中删除肿瘤一样,所有这些都将丢失。 谁能解释这种将数据与代码分离的做法是如何发生的以及它的发展方向?谁能引用知名人士的出版物,或者提供一些相关的数据,作为“新兴的诫命”来说明“从数据中分离代码”,并说明其起源? 1:甚至可以做出这样的区分。Lisp程序员,我在看着你。

6
我应该将特定功能提取到功能中,为什么?
我有一个执行3个任务的大型方法,每个任务都可以提取到一个单独的函数中。如果我将为每个任务添加其他功能,那么它会使我的代码变得更好还是更坏,为什么? 显然,它将在主函数中减少代码行的数量,但是将有附加的函数声明,因此我的类将具有附加的方法,我认为这不好,因为这会使类变得更加复杂。 我应该在编写所有代码之前执行此操作,还是在完成所有操作然后提取函数之前将其保留?


6
是否有一种设计模式可以消除检查标志的需要?
我将在数据库中保存一些字符串有效负载。我有两个全局配置: 加密 压缩 可以使用配置启用或禁用这些功能,方法是仅启用其中一个,两个都启用或两个都禁用。 我当前的实现是这样的: if (encryptionEnable && !compressEnable) { encrypt(data); } else if (!encryptionEnable && compressEnable) { compress(data); } else if (encryptionEnable && compressEnable) { encrypt(compress(data)); } else { data; } 我在考虑装饰器模式。是正确的选择,还是有更好的选择?

14
是否有某种语言或设计模式允许“删除”类层次结构中的对象行为或属性?
传统类层次结构的一个众所周知的缺点是,在对现实世界建模时,它们是不好的。例如,尝试用类来表示动物的种类。这样做确实存在几个问题,但是我从未见过的解决方案是,当子类“丢失”超类中定义的行为或属性时,例如企鹅无法飞行(有也许是更好的例子,但这是我想到的第一个)。 一方面,您不想为每个属性和行为定义一些标志来指定它们是否全部存在,并在访问该行为或属性之前每次对其进行检查。您只想说在Bird类中,鸟类可以简单,清晰地飞行。但是,如果以后可以定义“例外”而不必到处使用一些可怕的骇客,那就太好了。当系统生产一段时间后,通常会发生这种情况。您突然发现一个根本不适合原始设计的“例外”,并且您不想更改代码的很大一部分来容纳它。 因此,是否有一些语言或设计模式可以干净地处理此问题,而无需对“超类”以及使用它的所有代码进行重大更改?即使解决方案仅处理特定情况,也可以将多个解决方案一起形成一个完整的策略。 经过更多思考,我意识到我忘记了《里斯科夫替代原则》。这就是为什么你不能这样做。假设您为所有主要的“功能组”定义了“特征/接口”,则可以在层次结构的不同分支中自由实现特征,例如“飞翔”特征可以由Birds以及某些特殊的松鼠和鱼来实现。 因此,我的问题可能是“我如何取消实施特质?” 如果您的超类是Java可序列化的Java,则即使您无法对状态进行序列化(例如,如果您包含“ Socket”),您也必须也是一个。 一种方法是始终从一开始就成对定义所有特征:Flying和NotFlying(如果不进行检查,则会抛出UnsupportedOperationException)。非特征不会定义任何新接口,可以简单地进行检查。听起来像是“便宜”的解决方案,特别是如果从一开始就使用它。

12
哪种设计模式定义最差或定义最窄?[关闭]
对于每个编程项目,都有过编程经验的管理人员会在为您的项目推荐一些设计模式时大放异彩。当设计模式有意义或您需要可扩展的解决方案时,我喜欢它们。例如,我以积极的方式使用了代理,观察员和命令模式,并且每天都这样做。但是,如果只有一种创建对象的方法,我真的很犹豫地说出Factory模式,因为工厂将来可能会使一切变得更容易,但是却使代码复杂且纯属开销。 因此,我的问题是关于我的未来职业以及我对经理类型的回答,这些类型周围会出现随机的模式名称: 您使用了哪些设计模式,这使您整体退缩?哪些是最糟糕的设计模式,除了在一种有意义的单一情况下,您应该考虑哪些(请阅读:哪些设计模式定义非常狭窄)?(这就像我在寻找对亚马逊整体产品的负面评价,以了解使用设计模式的人最讨厌的东西。)而且我在这里不是在谈论反模式,而是通常被认为是“好的”模式。 编辑:正如一些回答所言,问题通常是模式不是“不良”而是“使用错误”。如果您知道一些经常被滥用甚至难以使用的模式,那么它们也可以作为答案。

4
在实现类中使用设计模式名称是个好主意吗?[关闭]
最近我碰到有大量的中等大蟒蛇的代码库来了MyClassAbstractFactory,MyClassManager,MyClassProxy,MyClassAdapter等类。 一方面,这些名称指示我研究和学习相应的模式,但它们并不能很好地描述班级的工作方式。 此外,他们似乎落在单词的列表禁止内编程:variable,process_available_information,data,amount,compute:过于宽泛的名字,不给我们介绍一下什么功能不能单独使用。 那么应该存在CommunicationManager还是宁愿PortListener?或者,也许我根本不理解问题...?

2
基于角色的REST API?
我正在构建一个REST API,具有不同角色的多个用户将可以访问它所包含的资源。 为了简化范围,让我们采用“学生/教师/班级”域: GET /students 是要访问的资源。 用户可能具有学生和/或老师之类的角色 学生将只能访问其班级的学生。老师将有机会接触所教课程的学生。一些用途可能是学生,也可能教其他课程。他们必须有权访问班级的学生和所教课程的学生。 理想情况下,我希望将其实现为两个功能-每个角色一个,如果用户具有多个角色,则“工会”。 我的问题是:我应该使用哪种模式来实现这一目标? 在外部 我应该按角色划分API吗?GET /teacher/students而GET /student/students这似乎并不合适的给我。 保留所有这些,我是一种资源(首选) 内部地 应该如何在内部实施? 每种方法都应该以BIG开关/如果每个角色开头吗? 我应该为每个角色实现一个存储库吗? 有没有一种设计模式可以帮助我实现这一目标? 附带说明一下:我正在使用ASP.NET Web API和Entity Framework 6,但这对于概念性实现来说并没有关系。

4
调解员与观察员?
有人能给我提供上的差异的规范答案Observer和Mediator,以及什么时候应该使用一个模式比其他的总结? 我不确定什么样的情况下需要一个Observer什么样的将需要Mediator

9
单例模式的替代方案
我对单例模式有不同的看法。一些人主张应不惜一切代价避免使用它,而另一些人则认为在某些情况下它可能是有用的。 我使用单例的一种情况是当我需要一个工厂(假设类型F的对象f)来创建某个类A的对象时。工厂使用一些配置参数创建一次,然后每次使用类型A被实例化。因此,要实例化A的代码的每个部分都获取单例f并创建新实例,例如 F& f = F::instance(); boost::shared_ptr<A> a = f.createA(); 所以我的一般情况是 出于优化原因(不需要多个工厂对象)或共享公共状态(例如,工厂知道仍可以创建A的实例),我只需要一个类的实例即可 我需要一种方法可以在代码的不同位置访问F的此实例f。 我对讨论此模式的好坏不感兴趣,但是假设我想避免使用单例,我还可以使用其他什么模式? 我的想法是(1)从注册表获取工厂对象,或(2)在程序启动期间的某个时候创建​​工厂,然后将工厂作为参数传递。 在解决方案(1)中,注册表本身是一个单例,因此我刚刚将不使用单例的问题从工厂转移到了注册表。 在情况(2)中,我需要工厂对象来自的一些初始源(对象),因此恐怕我会再次落入另一个单例(提供我的工厂实例的对象)。通过跟踪此单身人士链,我可以将问题简化为一个单身人士(整个应用程序),通过它 可以直接或间接管理所有其他单身人士。 最后一种选择(使用一个初始单例创建所有其他唯一对象并将所有其他单例注入正确的位置)是否可以接受?当有人建议不要使用单例时,这是隐式建议的解决方案,还是其他解决方案,例如在上述示例中? 编辑 由于我认为我的问题的重点已经被某些人误解了,因此这里提供了更多信息。如所解释的,例如这里,词语 单可指示(a)中的一类具有单个实例对象和(b)用于创建和访问这样的对象的设计模式。 为了使事情更清楚,让我们对(a)使用术语唯一对象, 对(b)使用术语单例模式。因此,我知道单例模式和依赖项注入是什么(顺便说一句,最近我一直在大量使用DI从我正在处理的某些代码中删除单例模式的实例)。 我的观点是,除非整个对象图都是从位于main方法堆栈上的单个对象实例化的,否则始终需要通过singleton模式访问一些唯一的对象。 我的问题是,完整的对象图创建和连接是否取决于主要方法(例如,通过一些不使用模式本身的强大DI框架)是唯一的无 单例模式解决方案。

5
使用NInject建立工厂的最佳方法是什么?
我对在MVC3中使用NInject进行依赖项注入非常满意。在MVC3应用程序中工作时,我使用NInject开发了一个自定义的Controller Creation Factory,因此所创建的任何控制器都将通过此Controller Factory注入依赖项。 现在,我开始开发Windows应用程序,我想使用应用程序范围依赖注入。即,必须通过NInject创建每个对象,以简化单元测试。请指导我确保创建的每个对象都只能通过NInject Factory。 例如,如果在Button_Click事件的任何Windows窗体上我都写: TestClass testClass = new TestClass() 并且TestClass有任何依赖,例如,ITest必须自动解决。我知道我可以使用: Ikernel kernel = new StandardKenel() //AddBinding() TestClass testClass = kenel.get<TestClass>(); 但是我发现每次要创建对象时都要执行此操作很麻烦。它还迫使开发人员以特定方式创建对象。可以做得更好吗? 我可以有一个用于对象创建的中央存储库,然后每个对象创建都会自动使用该存储库吗?

2
DDD-聚合根的存储库是否处理保存的聚合?
我正在对现有应用程序的未开发模块使用类似DDD的方法;由于架构原因,它不是100%DDD,但我正在尝试使用一些DDD概念。我有一个界上下文(我认为这是适当的期限-我仍然在学习DDD)由两个实体:Conversation和Message。对话是根源,因为没有对话就不存在消息,并且系统中的所有消息都是对话的一部分。 我有一个ConversationRepository类(尽管它实际上更像是一个网关,但我使用术语“存储库”)可以在数据库中找到会话。当找到会话时,它还会(通过工厂)为该会话创建消息列表(作为属性公开)。这似乎是正确的处理方式,因为似乎不需要完整的MessageRepository类,因为只有在检索到对话时才存在该类。 但是,在保存消息时,由于它是Message的聚合根,这是ConversationRepository的责任吗?我的意思是,我是否应该在ConversationRepository上有一个名为AddMessageMessage 的方法,该方法将Message作为参数并将其保存到数据库中?还是应该有一个单独的存储库来查找/保存消息?逻辑上似乎是每个实体一个存储库,但是我也听说过“每个上下文一个存储库”。

12
是否有描述这种编码方法的反模式?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 5年前关闭。 我有一个代码库,程序员倾向于将其包装在没有意义的区域中。例如,给定一个错误日志,我们可以通过 ErrorLog.Log(ex, "friendly message"); 他添加了其他各种方法来完成完全相同的任务。例如 SomeClass.Log(ex, "friendly message"); 它只是转过身来并调用第一个方法。这增加了复杂性级别,并且没有任何额外的好处。是否有一个反模式来描述这一点?

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.