我有一个创建对象集合的算法。这些对象在创建期间是可变的,因为它们最初很少,但是随后在算法中的不同位置填充了数据。
算法完成后,就决不能更改对象,但是对象会被软件的其他部分消耗。
在这些情况下,如下所述,拥有该类的两个版本是否被视为一种好习惯?
- 可变的是由算法创建的,然后
- 算法完成后,将数据复制到不可变的对象中,然后将其返回。
我有一个创建对象集合的算法。这些对象在创建期间是可变的,因为它们最初很少,但是随后在算法中的不同位置填充了数据。
算法完成后,就决不能更改对象,但是对象会被软件的其他部分消耗。
在这些情况下,如下所述,拥有该类的两个版本是否被视为一种好习惯?
Answers:
实现此目的的一种简单方法是拥有一个允许读取属性和仅调用只读方法的接口,以及一个实现该接口的类,该类也使您可以编写该类。
您创建它的方法,处理前者,然后返回后者,仅提供一个与之交互的只读接口。这将不需要复制,它使您可以轻松地微调希望调用者(而不是创建者)可以使用的行为。
举个例子:
public interface IPerson
{
public String FirstName
{
get;
}
public String LastName
{
get;
}
}
public class PersonImpl : IPerson
{
private String firstName, lastName;
public String FirstName
{
get { return firstName; }
set { firstName = value; }
}
public String LastName
{
get { return lastName; }
set { lastName = value; }
}
}
class Factory
{
public IPerson MakePerson()
{
PersonImpl person = new PersonImpl();
person.FirstName = 'Joe';
person.LastName = 'Schmoe';
return person;
}
}
这种方法的唯一缺点是可以将其简单地强制转换为实现类。如果是安全问题,那么仅使用此方法是不够的。一种解决方法是,您可以创建一个Facade类来包装可变类,该类仅提供调用者可以使用且不能访问内部对象的接口。
这样,连铸造都不会对您有帮助。两者都可以从相同的只读接口派生,但是强制转换返回的对象只会给您Facade类,这是不可变的,因为它不会更改包装的可变类的基础状态。
值得一提的是,这并不遵循通过不变构造函数一劳永逸地构造不可变对象的典型趋势。可以理解,您可能必须处理许多参数,但是您应该问自己是否需要预先定义所有这些参数,或者是否可以稍后引入。在这种情况下,应使用仅带有必需参数的简单构造函数。换句话说,如果它掩盖了程序中的另一个问题,请不要使用此模式。
您可以使用Builder模式为@JacquesB说,或者想为什么它实际上是你的这些对象必须在创建过程中是可变的?
换句话说,为什么创建它们的过程必须及时分散,而不是将所有必需的值一次性传递给构造函数并创建实例呢?
因为Builder可能是解决错误问题的好方法。
如果问题是您最终得到的构造函数的长度约为10个参数,并且希望通过一点一点地构建对象来减轻它的负担,则可能表明设计已被弄乱了,这10个值应为“袋装” /分为几个对象...或主要对象分为几个较小的对象...
在这种情况下-始终坚持不变,只要改进设计即可。