- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要复制一个具有很深的成员变量层次结构的对象(即该对象具有几个不同类型的成员,每个成员都有几个不同类型的成员,等等)。进行深层复制需要在许多类中实现clone()方法,这对于我的应用程序来说似乎有些过时了。
我想出的解决方案很简单,但是我想知道这是否是个坏主意。我的解决方案如下:
定义一个空接口Settings
。
定义一个名为IsCopyable
的接口,该接口具有方法getSettings()
和applySettings(Settings s)
。
对于实现X
的给定类IsCopyable
,将编写实现接口Settings
的类,其中包含必须复制到类X
的对象的“设置”。 (我通常将此类嵌套在类X
中,因此我具有X.Settings implements Settings
,但这可以在其他地方完成。)
然后,复制类X的实例:
X myX = new X();
// Stuff happens to myX.
// Now we want to copy myX.
X copyOfX = new X();
copyOfX.applySettings(myX.getSettings());
getSettings()
,将生成的
Settings
对象作为值传递给新实例上的
applySettings()
。 (当然,复制可以包装在名为copy()的成员中。)
最佳答案
我想对您的最后一个问题回答“是”,只是为了好玩:-)但是我知道您想要一些论点,所以让我尝试:
如果一个概念(在这里复制)对于一个对象是唯一的,那么您可以考虑将两者合并在同一个类中(这将在类本身中实现该方法)。例如:
如果对于某些对象,有多种复制方法,具体取决于...,则复制确实值得在原始对象之外进行。
如果对于所有对象,都有一种独特的复制方法,那么创建一个不同的对象进行复制真的有很多价值吗? (例如,如果总的复杂性太大,难以阅读和理解,那么最好将其分解)。
我一直很难通过调用显式构造函数来创建副本。原因是构造函数是唯一不能继承的方法(不包括静态变量...),因此它们不能通用(不可能为所有可复制对象提供唯一的接口)。这意味着在您的所有应用程序中,没有通用代码可以复制对象。每次尝试时,总有一段时间我确实需要以一般方式进行复制。
显式调用构造函数还意味着将来我将无法替换子类。假设您有一个对变量B起作用的算法A。如果给A子类B的子类,则当A复制其B变量(其实际类型为C)时,将使用B构造函数创建该副本。它不会属于同一类,并且可能会改变行为。因此,通过调用构造函数进行复制受到极大限制。
显式调用构造函数意味着无法使用接口。您可以在很多地方阅读有关接口的值...例如,在我们的应用程序中,没有直接在我们的代码中实例化许多对象,而是向Locator / Factory请求一个接口(或类),其中包含许多可能的优点(如果您的应用需要这一天):
如果我想在特定的上下文中将B子类替换为每个A对象,例如在某些自动化测试中衡量代价高昂的操作的性能,这非常容易。我们还需要用一个子类代替HashMaps,以找到一个插入到Map中并随后在序列化期间导致错误的不可修复对象。
如果我有接口,则创建对象仅涉及我的常规代码中的接口(Factory除外)。因此,我对具体的类完全没有依赖,就象您所知道的那样好(对接口的依赖具有更少的传递性依赖,并且更易于模拟以进行测试)。
在我们的例子中,这个工厂实际上是Spring支持的,因此实例化是通过Spring完成的。根据需要采取了许多其他步骤(代理,拦截,初始化方法...)。
在我们的应用程序中,我们通常最终会创建一个(或几个)克隆器。给定一个顶级对象,他们知道如何对其进行深层复制。通用克隆器的优点是代码只编写一次,对于整个应用程序都是通用的。通常,它也可以在应用程序之间重用...
实现:例如,使用反射,您可以递归地获取每个成员。但是,有许多陷阱要避免:
循环:A引用B引用C引用A。因此,我保留了已复制的对象的Map,引用了副本。当我复制对象但发现它已经存在于地图中时,我不会复制它,而是替换它已经完成的复制。
特殊类型:枚举不应该被复制(还有一些其他静态对象)。某些库类也可能会出现问题,因此您可以保留不想复制的特殊类的Set或Map,或以特殊方式复制。
您可能在最后的领域遇到麻烦...
具体情况
通常,某些特定对象的默认方式不正确。我们既需要通用的实现,又需要根据需要对其进行重载的可能性。对于他们,我们使用以下代码:
如果可以修改对象,则可以让他们实现特定的CustomizedCopier接口,并且该方法中的代码负责根据需要进行复制。如果通用代码看到此界面,则它不会执行任何操作。
如果我们不能修改对象(JRE,第三方代码...),则我们有一个Map / Registry Map,用于存储特定的类以及我们想要的特定复印机。请注意,有时这种技巧有时也并非用于定制复制,而是仅用于某些特殊用例,因为它可能会使复制对象的方式过载,因此通常仅用于某些特殊用例。
实际上,我通常会得到几个克隆器。例如,克隆数据持久实体通常使用此知识来进行不同的克隆(例如,id和audit字段可以设置为null)。
我通常也有一个执行相同的依赖项搜索的类,但出于其他需要:
toString()一个复杂的对象,用于为其创建调试字符串。
equals()和hashCode()实现(如果需要)。
将所有属性的对象图重新初始化为其默认值(考虑以多选项卡的巨大形式实现“重置”按钮)。
检查对象图中某处是否存在对象
控制对象图的可序列性(在某些情况下使用HttpSession进行序列化的典型用例;在开发中,我们显式检查对象,检测无法序列化的对象,并向开发人员提供最佳错误消息) 。
...
请注意,多线程通常需要复制。理想情况下,在多线程环境中重用的对象是不可变的。如果没有,通常建议克隆以确保程序全局一致性。
性能
使用反射并不总是那么快。通常,对于大量且经常使用的复制,我们将在对象本身中实现复制。但是我们发现只有少数几个类需要复制并且数量很大,因此这只是一般机制的一个例外,我们随后才插入(我在前面的文章中介绍了如何使用寄存器)当它们变得有用时。
关于design-patterns - 复制对象有哪些好的设计模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1386448/
这个问题在这里已经有了答案: Difference between / and /* in servlet mapping url pattern (5 个回答) 4年前关闭。 web.xml 中的/
Scala 具有支持模式匹配中析取的语言功能(“模式替代”): x match { case _: String | _: Int => case _ => } 但是,如果审查满足 P
解释我的问题: 类别:玩具 特质 1:说话像男性 特质2:说话像女性 我能否在运行时更改 Toy 的行为(特征),以便有时同一个对象说话像男性,有时同一个对象说话像女性? 我想在运行时改变说话行为。
我已经能够找到很好的资源,这些资源告诉我 Java API 中的 MouseAdapter 没有使用适配器模式。问题是:MouseAdapter 是否实现了某种模式? 我知道它的作用:它为 Mouse
我有兴趣了解有关模式识别的更多信息。我知道这是一个广泛的领域,所以我将列出一些我想学习处理的特定类型的问题: 在看似随机的字节集中查找模式。 识别图像中的已知形状(例如圆形和正方形)。 注意给定位置流
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
所以,问题很简单:在 awk 中,if (var ~/pattern/) 是否与 if (var ~ "pattern") 相同? 我已经对 csv 进行了一些基本测试,两者似乎都产生了相同的结果..
我的问题是 this 的 Scala (Java) 变体Python 上的查询。 特别是,我有一个字符串 val myStr = "Shall we meet at, let's say, 8:45
我最近一直在研究正则表达式并注意到了这一点。 Pattern pNoEmbed = Pattern.compile("[ a-z]+", Pattern.CASE_INSENSITIVE); Patt
在研究大型应用程序的 C++ 源代码时,我发现了这种模式(该示例的语法可能很粗略,但基本细节都在那里): class A : X friend B; B *parent; ...
有人可以举一个“中介者模式”在现实世界中有用的用例吗? 最佳答案 Mediator是一种添加第三方对象以控制一组(2 个或更多)对象之间交互的方法。 您能找到的最简单的示例是 Chat Room例如,
尝试编译以下代码片段时: type 'a frame = Empty | Frame of string * 'a * 'a frame let rec searchFrame f s = match
目标 我的目标是获得一个 servlet 过滤器来处理对主页的请求,然后再将它们转发到 index.jsp。 问题 我无法让过滤器接收来自“/”的请求。它的 URL 模式是 / 相反,对该模式的请求最
这个问题已经有答案了: Difference between / and /* in servlet mapping url pattern (5 个回答) 已关闭 6 年前。 我已经设置了一个具有此
第 6 章(代码重用模式)中有以下示例: // the parent constructor function Parent(name) { this.name = name || 'Adam
Pattern类中的pattern()方法和toString()方法有什么区别? 文档说: public String pattern() Returns the regular expression
我有脚本 here并且 ng-pattern 工作正常,因为 scope.subnet 仅在输入匹配模式后才显示在输出中。但是如果 ng-pattern 不匹配,ng-show 不会显示任何错误
我想知道为什么当提供相同的正则表达式和相同的字符串时,java regex pattern.matcher() 和 pattern.matches() 的结果会不同 String str = "hel
This SO answer引用“患有模式综合症的小男孩”。虽然我可以通过上下文推断出一些含义,但我并不完全理解。 “有模式综合症的小男孩”的良好定义是什么? 最佳答案 它只是意味着寻找将模式注入(i
我有以下微服务架构的用例。 我的问题是,在当前情况下,我有 3 个微服务和一个 APIGateway。 最后,网关必须在聚合(组合)来自 3 个服务的数据之前进行大量查询。因为这 3 个微服务只提供基
我是一名优秀的程序员,十分优秀!