Questions tagged «design-patterns»

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

13
MVC中的M在哪里?
我试图将我的应用程序重构为MVC,但是我坚持使用M部分。 在数据库支持的应用程序中,该模型是在应用程序代码中实现的,对吗? 但是,数据库中有什么-模型也不是吗? (我没有将数据库用作简单的对象存储-数据库中的数据是企业资产)。

8
什么时候应该消除复杂性?
通过在需要之前实施设计模式来过早引入复杂性不是一个好习惯。 但是,如果您遵循所有(或什至大部分)SOLID原则并使用通用的设计模式,那么随着功能或需求的添加或更改,以使您的设计保持所需的可维护性和灵活性,您将引入一些复杂性。 但是,一旦引入了这种复杂性并像冠军一样工作,何时将其删除? 例。我有一个为客户编写的应用程序。在最初创建时,那里有几种向员工加薪的方法。我使用了策略模式和工厂来使整个过程保持整洁。随着时间的流逝,应用程序所有者添加或删除了某些升高方法。 时间流逝,新主人接管了。这个新主人刻薄了鼻子,保持一切简单,只有一种加薪的方法。 不再需要策略模式所需的复杂性。如果我现在按照需求在哪里编写代码,那么我不会介绍这种额外的复杂性(但请确保在需要时我可以花很少的精力或根本不用做任何工作来引入它)。 那我现在要删除策略实施吗?我认为这个新主人不会改变加薪的方式。但是应用程序本身已经证明了这可能发生。 当然,这只是新所有者接管并简化了许多流程的应用程序中的一个示例。我可以删除数十个类,接口和工厂,并使整个应用程序更加简单。请注意,当前的实现确实可以很好地工作,并且所有者对此感到满意(由于所讨论的复杂性,我能够如此迅速地实现她的更改感到惊讶甚至高兴)。 我承认这一怀疑的一小部分是因为新所有者很可能不再使用我了。我真的不在乎其他人会接手这件事,因为它并不是一个巨大的收入来源。 但我确实关心2件(相关的)事情 我有点担心,新维护者在尝试理解代码时将不得不加倍努力。复杂性就是复杂性,我不想激怒追随我的心理狂。 但是,更令我担心的是竞争对手看到了这种复杂性,并认为我只是实施设计模式来增加工作时间。然后散布这个谣言来伤害我的其他生意。(我听说过此事。) 所以... 总的来说,即使以前需要的复杂性行之有效,并且历史上已经证明了对这种复杂性的需求,但是否应该删除它却没有迹象表明将来会需要它呢? 即使上面的问题通常被回答为“否”,如果将项目移交给竞争对手(或陌生人),消除这种“不必要的”复杂性是否明智?

3
关于如何减少“经理”类使用的提示/建议?
有时,我听说程序设计中有太多“管理器”类是代码的味道,并增加了不必要的复杂性。对我而言,人们想使用管理器类从对他们有意义的上下文中使用对象来控制和控制对象是有道理的,但是弄清楚如何使解决方案在没有它们的情况下有效。 真的应该尽可能避免经理班吗?另外,对于应删除这些管理人员的一般/常见情况,我应该阅读哪些文章/论文,以了解如何实施替代方法?

12
使用条件句是否是反模式?
我在工作中的遗留系统中看到了很多东西-这些功能如下所示: bool todo = false; if(cond1) { ... // lots of code here if(cond2) todo = true; ... // some other code here } if(todo) { ... } 换句话说,功能有两个部分。第一部分进行某种处理(可能包含循环,副作用等),并沿途设置“ todo”标志。仅当已设置“ todo”标志时才执行第二部分。 这似乎是一种非常丑陋的处理方式,而且我认为我花了很多时间去理解的大多数情况都可以重构,以避免使用该标志。但这是一个实际的反模式,一个坏主意还是完全可以接受? 第一个明显的重构是将其分为两种方法。但是,我的问题更多是关于是否有必要(在现代的OO语言中)创建一个局部标志变量,可能将其设置在多个位置,然后在以后使用它来决定是否执行下一个代码块。

3
接口作为行为的抽象基类?
我需要为我的C#项目设计一个类层次结构。基本上,类的功能类似于WinForms类,因此让我们以WinForms工具包为例。(但是,我不能使用WinForms或WPF。) 每个类都需要提供一些核心属性和功能。尺寸,位置,颜色,可见性(对/错),绘制方法等。 我需要设计建议我使用了一个带有抽象基类和接口的设计,这些基类和接口不是真正的类型,而更像是行为。这是一个好的设计吗?如果没有,那将是一个更好的设计。 代码如下: abstract class Control { public int Width { get; set; } public int Height { get; set; } public int BackColor { get; set; } public int X { get; set; } public int Y { get; set; } public int BorderWidth { get; set; } …

2
Java IO类中是否存在Decorator Pattern?
对于一项作业,我必须找出四个类的设计模式中的哪个类java.io.Reader及其子类java.io.PushbackReader,java.io.BufferedReader并使用java.io.FilterReader它们进行构建。 根据这篇文章,设计模式将是装饰器模式。这仅对我有意义PushbackReader,BufferedReader并且FilterReader可以装饰成可以同时使用,从而有效地创建了一个BufferedPushbackFilterReader。是这个主意吗?

3
如何为Winforms解决方案设置MVP?
我过去曾经使用过MVP和MVC,我更喜欢MVP,因为我认为它可以更好地控制执行流程。 我已经创建了我的基础结构(数据存储/存储库类),并且在对示例数据进行硬编码时可以毫无问题地使用它们,因此现在我转向GUI并准备我的MVP。 A节 我已经看到MVP使用视图作为入口点,也就是说,在视图构造方法中,它创建了演示者,该演示者又创建了模型,并根据需要连接事件。 我还以演示者为切入点,在其中创建了视图,模型和演示者,然后在其构造函数中为该演示者提供了视图和模型对象以关联事件。 与2中一样,但是模型没有传递给演示者。相反,该模型是一个静态类,在其中调用方法并直接返回响应。 B区 在使视图和模型保持同步方面,我已经看到了。 每当视图中的值发生更改时,即TextChanged.Net / C#中的事件。这会触发一个DataChangedEvent传递到模型中的,以使其始终保持同步。在模型发生变化的地方(即它侦听的后台事件),然后通过引发的相同想法来更新视图DataChangedEvent。当用户想要提交更改SaveEvent时,它将触发,并进入模型进行保存。在这种情况下,模型将模仿视图的数据并处理动作。 与#b1相似,但是视图并非始终与模型同步。相反,当用户想要提交更改时,将SaveEvent被解雇,演示者获取最新的详细信息并将其传递到模型中。在这种情况下,除非需要对视图数据进行操作,否则模型将不知道视图数据,在这种情况下,将传递所有必需的详细信息。 C区 在视图中显示业务对象,即不是原始数据的对象(MyClass)(int,double) 该视图具有将显示为域/业务对象的所有数据的属性字段。例如,view.Animals公开一个IEnumerable<IAnimal>属性,即使视图将它们处理到TreeView中的Nodes中。然后对于选定的动物,它将SelectedAnimal作为IAnimal属性公开。 该视图不了解域对象,它仅公开图元/框架(.Net / Java)包含的对象类型的属性。在这种情况下,演示者将把适配器对象传递给域对象,然后适配器将给定的业务对象转换为视图上可见的控件。在这种情况下,适配器必须有权访问视图上的实际控件,而不仅仅是任何视图,因此会变得更加紧密。 D区 用于创建单个控件的多个视图。即,您有一个具有简单模型的复杂视图,例如保存不同类型的对象。您可以在侧面有一个菜单系统,每单击一个项目就会显示相应的控件。 您创建一个巨大的视图,其中包含通过视图界面公开的所有单个控件。 您有几种看法。您有一个菜单视图和一个空白面板。该视图创建所需的其他视图,但不显示它们(visible = false),该视图还为其包含的每个视图(即子视图)实现接口,因此可以向一个演示者公开。空白面板中将填充其他视图(Controls.Add(myview))和((myview.visible = true)。这些“子”视图中引发的事件由父视图处理,父视图又将事件传递给演示者,反之亦然,以将事件提供给子元素。 每个视图(无论是主要父视图还是较小的子视图)均连接到自己的演示者和模型中。您可以从文化上将视图控件放到现有的表单中,它将具备功能,只需将其连接到幕后的演示者中即可。 E节 如果所有内容都具有接口,那么现在基于以上示例中MVP的完成方式,由于它们可能不是交叉兼容的,因此将影响此答案。 一切都有界面,视图,演示者和模型。然后,显然每个都有具体的实现。即使您只有一个具体的视图,模型和演示者。 视图和模型具有接口。这允许视图和模型不同。演示者创建/获得视图和模型对象,并且仅用于在它们之间传递消息。 仅视图具有界面。该模型具有静态方法,不会创建,因此不需要接口。如果需要其他模型,则演示者将调用一组不同的静态类方法。由于模型是静态的,因此与演示者没有链接。 个人想法 从我介绍的所有不同变体中(大多数我可能已经以某种形式使用过),我确信还有更多。我更喜欢A3,因为它可以使业务逻辑在MVP之外可重用,而B2则可以减少数据重复和触发事件。C1用于不添加其他类,请确保将少量非单元可测试的逻辑放入视图中(如何可视化域对象),但是可以对其进行代码审查,也可以在应用程序中简单地对其进行查看。如果逻辑很复杂,我会同意一个适配器类,但并非在所有情况下都同意。对于D部分,我觉得D1创建的视图对于菜单示例来说至少太大了。我以前用过D2和D3。D2的问题是,您最终不得不编写大量代码才能将事件往返于演示者与演示者之间路由到正确的子视图,并且其拖放操作不兼容,每个新控件都需要更多接线才能支持单个演示者。D3是我的首选,但是即使视图恰好非常简单或不需要重用,D3仍会作为演示者和模型添加更多类来处理该视图。我认为根据情况,D2和D3的混合效果最好。对于E部分,我认为具有接口的所有内容都可能过头了,因为我已经对域/业务对象进行了此操作,因此这样做通常不会在“设计”中看到任何优势,但它确实有助于在测试中模拟对象。我个人认为E2是经典的解决方案,尽管我以前在2个项目中使用过E3。我认为根据情况,D2和D3的混合效果最好。对于E部分,我认为具有接口的所有内容都可能会过时了,我已经对域/业务对象进行了此操作,并且这样做通常不会在“设计”中看到任何优势,但是它确实有助于在测试中模拟对象。我个人认为E2是经典的解决方案,尽管我以前在2个项目中使用过E3。我认为根据情况,D2和D3的混合效果最好。对于E部分,我认为具有接口的所有内容都可能会过时了,我已经对域/业务对象进行了此操作,并且这样做通常不会在“设计”中看到任何优势,但是它确实有助于在测试中模拟对象。我个人认为E2是经典的解决方案,尽管我以前在2个项目中使用过E3。 题 我是否正确实施MVP?有正确的方法吗? 我已经读过Martin Fowler的著作,其中有很多变化,而且我还记得当我刚开始做MVC时,我理解了这个概念,但是最初无法确定切入点在哪里,一切都有自己的功能,但是控制和创建原始作品的是什么MVC对象集。

6
纯功能vs告诉,不要问?
“函数的理想参数个数为零”是完全错误的。理想的参数数目恰好是使函数不受副作用影响所需的数目。少于这个数目,您不必要地导致您的功能不纯净,从而迫使您远离成功之路,攀登痛苦的梯度。有时“鲍勃叔叔”会在他的建议下出现。有时他错得很厉害。他的零论点建议就是后者的一个例子 (来源:@David Arno在此站点上的另一个问题下的评论) 该评论获得了133个投票的惊人成绩,这就是为什么我想更加关注它的优点。 据我所知,编程有两种不同的方式:纯函数式编程(此评论令人鼓舞)和告诉,不要问(不时建议在本网站上推荐)。AFAIK这两个原则从根本上是不兼容的,彼此之间几乎是相反的:纯函数可以概括为“仅返回值,没有副作用”,而告诉,不问可以概括为“不返回任何东西,只有副作用”。另外,我有点困惑,因为我认为告诉,不要问,它被视为OO范式的核心,而纯函数则被视为功能范式的核心-现在,我看到了OO中推荐的纯函数! 我想开发人员应该选择这些范例之一并坚持下去吗?好吧,我必须承认,我永远也无法跟随自己。通常,返回值对我来说似乎很方便,而且我真的看不到如何仅凭副作用实现我想达到的目标。通常,对我来说副作用很方便,而且我真的看不到如何仅通过返回值就能达到我想要达到的目的。而且,有时(我想这太可怕了),我有两种方法都能做到。 但是,从这133个投票中,我认为当前纯函数式编程正在“取胜”,因为它已成为一种共识,说出来更好,不要问。它是否正确? 因此,在这个反模式化游戏的示例中,我尝试制作:如果我想使其符合纯功能范式-怎么办?! 对我来说,拥有战斗状态似乎是合理的。由于这是基于回合的游戏,因此我将战斗状态保留在字典中(多人游戏-可能有许多玩家同时进行许多战斗)。每当玩家回合时,我都会在战斗状态上调用适当的方法,该方法会(a)相应地修改状态,然后(b)向玩家返回更新,这些更新会序列化为JSON,并且基本上只是告诉他们发生了什么板。我想,这是在公然违反两项原则的同时。 好的-如果我确实想,我可以制定一个方法返回战斗状态,而不是就地修改它。但!然后,我是否将不得不复制战斗状态中的所有内容,只是为了返回一个全新的状态,而不是就地进行修改? 现在,如果此举是一种攻击,那么我可以返回一个更新了HP的角色?问题是,这不是那么简单:游戏规则,一举一动不仅会消除一部分玩家的生命值,而且往往会产生更多的影响。例如,它可能会增加字符之间的距离,应用特殊效果等。 对我来说,只需修改适当的状态并返回更新就简单得多了。 但是,经验丰富的工程师将如何解决这个问题?

2
面向对象与基于矢量的编程
我陷入了面向对象和基于矢量的设计之间。我喜欢对象赋予整个建筑的能力,结构和安全性。但是同时,速度对我来说非常重要,并且在数组中具有简单的float变量确实对基于矢量的语言/库(例如Matlab或Python中的numpy)有所帮助。 这是我写来说明我的观点的一段代码 问题:添加拖车波动率数字。如果x和y是两个波动率数字,则波动率的总和为(x ^ 2 + y ^ 2)^ 0.5(假设有一定的数学条件,但在这里并不重要)。 我想非常快地执行此操作,同时我需要确保人们不要以错误的方式(x + y)添加波动率。两者都很重要。 基于面向对象的设计将是这样的: from datetime import datetime from pandas import * class Volatility: def __init__(self,value): self.value = value def __str__(self): return "Volatility: "+ str(self.value) def __add__(self,other): return Volatility(pow(self.value*self.value + other.value*other.value, 0.5)) (此外:对于那些不熟悉Python的人来说,__add__它只是一个覆盖+运算符的函数) 假设我添加了两个波动率列表 n = 1000000 vs1 = Series(map(lambda …

3
在MVC中,应从Controller或Model调用DAO
我已经看到了很多反对直接从Controller类调用DAO以及从Model类调用DAO的争论。事实上,我个人觉得如果我们遵循MVC模式,则控制器不应与DAO耦合,而应与Model类耦合应该从内部调用DAO,而控制器应该调用模型类。为什么,我们可以将模型类与Web应用程序分离开来,并公开各种功能,例如REST服务使用我们的模型类。 如果我们在控制器中编写DAO调用,REST服务将无法重用功能,对吗?我总结了以下两种方法。 方法1 public class CustomerController extends HttpServlet { proctected void doPost(....) { Customer customer = new Customer("xxxxx","23",1); new CustomerDAO().save(customer); } } 方法#2 public class CustomerController extends HttpServlet { proctected void doPost(....) { Customer customer = new Customer("xxxxx","23",1); customer.save(customer); } } public class Customer { ........... private void save(Customer customer){ …

3
DAO应该是单身吗?
我正在开发RESTful API,我认为为我的资源使用DAO会很方便,因为尽管我计划仅使用内存来存储它们,但是我不想对使用库的任何人敞开大门,如果他们决定使用DAO的数据库实现。 我的问题是DAO是否应为单例。如果不是,则该服务将具有DAO的实例,并且看起来大致如下: @Path("eventscheduler") public class EventSchedulerService { private IEventSchedulerDao dao = new EventSchedulerDao(); // in case a different implementation is to be used public void setEventSchedulerDao(IEventSchedulerDao dao) { this.dao = dao; } @Path("{uniqueName}") @GET @Produces(MediaType.APPLICATION_JSON) public Tournament getTournament(@PathParam("name") String uniqueName) { return dao.get(uniqueName); } @Path("create") @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public …


3
Model-View-Controller:用户是否与View或Controller交互?[关闭]
已关闭。这个问题需要细节或说明。它当前不接受答案。 想改善这个问题吗?添加细节并通过编辑此帖子来澄清问题。 5年前关闭。 我最近了解了MVC设计模式。我正在从《 Head First设计模式》一书中学习。 根据这本书(如果我理解正确的话): 该模型是大多数应用程序逻辑和数据。 View基本上是一个GUI,它向用户直观地表示模型。 控制器负责“调解”,并充当视图和模型之间的“中间人”。视图向控制器报告用户已执行操作,控制器将其转换为模型上的方法调用。 但是,网上很多地方都与我从那本书中了解的内容相矛盾。他们声称,一般而言,用户是与控制器(而不是视图)交互的。 哪一个是正确的或更常见的?用户是直接与Controller交互还是与View直接交互?两种方法都可以接受吗?哪个更常见?

7
是否可以在没有明显分支的情况下实施策略模式?
策略模式很好地避免了if ... else庞大的构造,并使添加或替换功能更加容易。但是,我认为这仍然存在一个缺陷。似乎在每个实现中仍然需要一个分支构造。它可能是工厂或数据文件。以订购系统为例。 厂: // All of these classes implement OrderStrategy switch (orderType) { case NEW_ORDER: return new NewOrder(); case CANCELLATION: return new Cancellation(); case RETURN: return new Return(); } 此后的代码无需担心,现在只有一个地方可以添加新的订单类型,但是此部分代码仍不可扩展。将其拉出到数据文件中有助于提高可读性(我知道这值得商bat): <strategies> <order type="NEW_ORDER">com.company.NewOrder</order> <order type="CANCELLATION">com.company.Cancellation</order> <order type="RETURN">com.company.Return</order> </strategies> 但这仍然增加了样板代码来处理数据文件-授予的,更容易进行单元测试和相对稳定的代码,但是仍然增加了复杂性。 而且,这种结构不能很好地进行集成测试。现在每个单独的策略可能更容易测试,但是您添加的每个新策略都增加了测试的复杂性。它比没有使用模式时要少,但是它仍然存在。 有没有办法实现减轻这种复杂性的战略模式?还是这只是简单而已,而尝试更进一步只会增加另一层抽象,却几乎没有好处?

4
具有不同输入参数的工人的C#设计模式
我不确定哪种设计模式可以帮助我解决此问题。 我有一个类“ Coordinator”,该类确定应使用哪种Worker类-不必知道那里有所有不同类型的Worker-它仅调用WorkerFactory并根据通用IWorker接口起作用。 然后,它将适当的Worker设置为工作并返回其“ DoWork”方法的结果。 到目前为止还不错。我们对新的Worker类有一个新的要求,即“ WorkerB”,它需要额外的信息量,即额外的输入参数,才能使其工作。 就像我们需要一个带有额外输入参数的DoWork方法重载...但是所有现有的Workers都必须实现该方法-这似乎是错误的,因为这些Workers确实不需要该方法。 我该如何重构,以使协调器不知道正在使用哪个工作人员,并且仍然允许每个工作人员获取完成其工作所需的信息,但没有任何工作人员执行不需要的信息? 已经有很多现有的工人。 我不想更改任何现有的具体Workers来适应新WorkerB类的要求。 我以为Decorator模式在这里会很好,但是我之前没有看到任何Decorator用相同的方法但参数不同来装饰对象... 代码情况: public class Coordinator { public string GetWorkerResult(string workerName, int a, List<int> b, string c) { var workerFactor = new WorkerFactory(); var worker = workerFactor.GetWorker(workerName); if(worker!=null) return worker.DoWork(a, b); else return string.Empty; } } public class WorkerFactory { …

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.