问题描述
我无法获得我们需要一成不变的类的情况.
您是否曾经面临过任何这样的要求?或者,请给我们任何真正应该使用此模式的真实示例.
推荐答案
其他答案似乎过于专注于解释为什么不变性是好的.它非常好,我尽可能使用它. 但是,这不是您的问题.我会逐点提出您的问题,以确保您获得所需的答案和示例.
我无法获得我们需要一成不变的类的情况.
"需求"是这里的相对术语.不变的类是一种设计模式,就像任何范式/模式/工具一样,它都可以使构造软件更容易.同样,在OO范式出现之前,编写了很多代码,但是我将我算在"需要" oo的程序员中.不变的课程,例如OO,并不严格需要,但我会像我需要它们一样行事.
您是否曾经面临过任何此类要求?
如果您没有以正确的视角查看问题域中的对象,则可能不会看到不可变的对象的要求.如果您不熟悉何时有利地使用它们,则可能很容易想到问题域不需要任何不可变的类.
我经常使用不变的类,其中我认为问题域中的一个给定对象是一个值或固定实例.这个概念有时取决于视角或观点,但理想情况下,很容易切换到正确的视角以识别良好的候选对象.
,您可以通过确保阅读各种书籍/在线文章的阅读,从而更好地了解不变的物体的真正有用(如果不是严格必要的话)关于不变的课程.一篇很好的文章让您入门的是 java理论和实践:突变?
我将尝试在下面举几个示例,说明如何以不同的视角看到对象(与不可变的可变)来澄清我的含义.
...您能给我们任何真实的例子,我们应该使用此模式.
由于您要求提供真实的例子,我会给您一些,但首先,让我们从一些经典的例子开始.
经典价值对象
字符串和整数通常被认为是值.因此,发现字符串类和整数包装类(以及其他包装器类)在Java中是不可能的,这并不奇怪.通常认为颜色是一个值,因此是不可变的颜色类.
反例
相反,通常不认为汽车是价值对象.建模汽车通常意味着创建具有变化状态的类(里程表,速度,燃油水平等).但是,在某些域中,它可能是一个值对象.例如,可以将汽车(或尤其是汽车型号)视为应用程序中的价值对象,以查找给定车辆的适当机油.
扑克牌
曾经编写扑克牌程序?我做到了.我本可以将扑克牌代表为具有可变西装和排名的可变对象.扑克手可以是5个固定实例,在我手中替换第五张卡片将意味着通过更改西装和排名ivars将第五次扑克牌实例突变为新卡.
但是,我倾向于将扑克牌视为一个不变的物体,它具有固定的不变西装,并且曾经创建了排名.我的抽扑克手将是5个实例,并在我的手中替换卡片将涉及丢弃其中一个实例并在我的手中添加一个新的随机实例.
地图投影
最后一个示例是我在某些地图代码上工作时,地图可以在各种 Projections .原始代码的地图使用固定但可变的投影实例(如上面的可变play牌).更改地图投影意味着突变地图的投影实例的IVAR(投影类型,中心点,变焦等).
但是,如果我认为投影是不变的值或固定实例,我觉得设计会更简单.更改地图投影意味着让映射引用不同的投影实例,而不是突变地图的固定投影实例.这也使捕获命名的投影变得更加简单,例如MERCATOR_WORLD_VIEW.
其他推荐答案
一般而言,不可变的类是更简单地设计,实现和使用.一个示例是字符串:java.lang.String的实现比C ++中的std::string的实现明显简单,主要是由于其不可分性.
不可变形使特别差异的一个特定领域是并发:不可变的物体可以在多个线程之间安全共享,而必须通过仔细的设计和实现使可变的对象进行线程安全 - 通常是这样 - 通常是这样远离琐碎的任务.
更新: 有效Java第二版详细解决此问题 - 请参见项目15:最小化Mutability .
另请参见以下相关文章:
其他推荐答案
Joshua Bloch的有效Java概述了写不变的几个理由:
- 简单性 - 每个类仅在一个状态
- 线程安全 - 因为状态无法更改,因此不需要同步
- 以不变的样式写作可以导致更强大的代码.想象一下字符串是否不变;返回字符串的任何Getter方法都需要实现在返回字符串之前创建防御副本 - 否则客户端可能会意外或恶意破坏对象的状态.
通常,除非有严重的性能问题,否则最好使物体不变.在这种情况下,可变的构建器对象可用于构建不变的物体,例如StringBuilder
问题描述
I am unable to get what are the scenarios where we need an immutable class.
Have you ever faced any such requirement? or can you please give us any real example where we should use this pattern.
推荐答案
The other answers seem too focused on explaining why immutability is good. It is very good and I use it whenever possible. However, that is not your question. I'll take your question point by point to try to make sure you're getting the answers and examples you need.
I am unable to get what are the scenarios where we need an immutable class.
"Need" is a relative term here. Immutable classes are a design pattern that, like any paradigm/pattern/tool, is there to make constructing software easier. Similarly, plenty of code was written before the OO paradigm came along, but count me among the programmers that "need" OO. Immutable classes, like OO, aren't strictly needed, but I going to act like I need them.
Have you ever faced any such requirement?
If you aren't looking at the objects in the problem domain with the right perspective, you may not see a requirement for an immutable object. It might be easy to think that a problem domain doesn't require any immutable classes if you're not familiar when to use them advantageously.
I often use immutable classes where I think of a given object in my problem domain as a value or fixed instance. This notion is sometimes dependent on perspective or viewpoint, but ideally, it will be easy to switch into the right perspective to identify good candidate objects.
You can get a better sense of where immutable objects are really useful (if not strictly necessary) by making sure you read up on various books/online articles to develop a good sense of how to think about immutable classes. One good article to get you started is Java theory and practice: To mutate or not to mutate?
I'll try to give a couple of examples below of how one can see objects in different perspectives (mutable vs immutable) to clarify what I mean by perspective.
... can you please give us any real example where we should use this pattern.
Since you asked for real examples I'll give you some, but first, let's start with some classic examples.
Classic Value Objects
Strings and integers are often thought of as values. Therefore it's not surprising to find that String class and the Integer wrapper class (as well as the other wrapper classes) are immutable in Java. A color is usually thought of as a value, thus the immutable Color class.
Counterexample
In contrast, a car is not usually thought of as a value object. Modeling a car usually means creating a class that has changing state (odometer, speed, fuel level, etc). However, there are some domains where it car may be a value object. For example, a car (or specifically a car model) might be thought of as a value object in an app to look up the proper motor oil for a given vehicle.
Playing Cards
Ever write a playing card program? I did. I could have represented a playing card as a mutable object with a mutable suit and rank. A draw-poker hand could be 5 fixed instances where replacing the 5th card in my hand would mean mutating the 5th playing card instance into a new card by changing its suit and rank ivars.
However, I tend to think of a playing card as an immutable object that has a fixed unchanging suit and rank once created. My draw poker hand would be 5 instances and replacing a card in my hand would involve discarding one of those instance and adding a new random instance to my hand.
Map Projection
One last example is when I worked on some map code where the map could display itself in various projections. The original code had the map use a fixed, but mutatable projection instance (like the mutable playing card above). Changing the map projection meant mutating the map's projection instance's ivars (projection type, center point, zoom, etc).
However, I felt the design was simpler if I thought of a projection as an immutable value or fixed instance. Changing the map projection meant having the map reference a different projection instance rather than mutating the map's fixed projection instance. This also made it simpler to capture named projections such as MERCATOR_WORLD_VIEW.
其他推荐答案
Immutable classes are in general much simpler to design, implement and use correctly. An example is String: the implementation of java.lang.String is significantly simpler than that of std::string in C++, mostly due to its immutability.
One particular area where immutability makes an especially big difference is concurrency: immutable objects can safely be shared among multiple threads, whereas mutable objects must be made thread-safe via careful design and implementation - usually this is far from a trivial task.
Update: Effective Java 2nd Edition tackles this issue in detail - see Item 15: Minimize mutability.
See also these related posts:
其他推荐答案
Effective Java by Joshua Bloch outlines several reasons to write immutable classes:
- Simplicity - each class is in one state only
- Thread Safe - because the state cannot be changed, no synchronization is required
- Writing in an immutable style can lead to more robust code. Imagine if Strings weren't immutable; Any getter methods that returned a String would require the implementation to create a defensive copy before the String was returned - otherwise a client may accidentally or maliciously break that state of the object.
In general it is good practise to make an object immutable unless there are severe performance problems as a result. In such circumstances, mutable builder objects can be used to build immutable objects e.g. StringBuilder