我有一个大班,我们称之为'国家'。它有各种属性,如List States,Age等。
在现实生活中,我正在开发一个ASP.NET应用程序,用户可以在其中注册我们客户提供的服务的订阅。他们需要填写的这个应用程序表单有很多属性,表示数据模型的主要类之一变得过于臃肿,所以我想通过组合将它分解为小类,但是仍然在链接到父类的子类上有属性类。
这个例子是为了简单起见并参考汽车示例。所以我们有一个名为Country的类,如下所示:
public static class WorldDatabase
{
public static List<Country> Countries {get;set;}
}
class Country
{
public int Age {get;set;}
public string Name{get;set;}
public List<State> States{get;set;}
}
class State
{
public string CountryName{get;set;}
public string Capitol{get;set;}
public List<string> Cities{get;set;}
}
现在,创建一个快速的设置示例:
var states = new List<States>();
states.Add(new State(){CountryName="United States",
StateName="NJ",
Capitol="Trenton"});
WorldDatabase.Countries.Add(new Country{Age=237,
Name="United States",
States=states});
WorldDatabase.Countries[0].Name="US";
//assert obviously fails because the names are not linked
Assert.IsEqual(WorldDatabase.Countries[0].Name == states[0].CountryName);
所以我试图解决的问题是:链接这两个属性的最佳方法是什么?我想出的方法是将父(Country)的实例注入State类。但是我担心孩子不应该对父母做出改变。此外,似乎可能有一种方法可以使用我不知道的更少的代码来完成此操作。以下是我提出的两种方式:
//does a one-time 'binding'
class State
{
public void BindFrom(Country country)
{
CountryName=country.Name;
}
public string CountryName{get;set;}
public string Capitol{get;set;}
public List<string> Cities{get;set;}
}
//tracks the parent forever
class State
{
private readonly Country _parent;
public State(Country parent)
{
_parent = parent;
}
public string CountryName
{
get
{
return _parent.Name;
}
}
public string Capitol{get;set;}
public List<string> Cities{get;set;}
}
这种模式的名称是什么(如果它是一个)?我想了解更多关于它...还有其他选择吗?
答案 0 :(得分:1)
您的probelem可以通过使用父类实现/继承的接口或基类来解决。
接口/基类应该只显示您希望子项能够查看或修改的参数。只有完整的实现才允许写作。
class CountryBase
{
public string Name { get; protected set; }
}
class Country: CountryBase
{
public string Name { get { return base.Name;} set { base.Name = value;}
}
Country
现在可以完全控制CountryBase.Name
的setter。仅将CountryBase
传递给您的State
个实例。
或者,作为界面(我的推荐);
class ICountry
{
string Name { get;}
}
class Country: ICountry
{
public string Name { get; set; }
}
答案 1 :(得分:1)
我看到的唯一一个与你的例子相近的模式是委托模式(名称的检索被委托给州的父母)。
你的例子让我想起了聚会和作文之间的区别:一个国家有几个州,没有任何意义可以让一个国家不属于一个国家。
我猜两种解决方案各有利弊。但是,我将第一个更改为只知道CountryName而不是在构造函数中传递国家/地区。如果在构造函数中更改了国家/地区名称,那么使用CountryName的公共setter打破数据封装有什么意义呢?
答案 2 :(得分:0)
看起来国家应该引用它所属的国家。这种模式称为Object composition。
答案 3 :(得分:0)
我不知道这是什么模式,但是看看你的例子,我认为你面临的问题是属性内容被改变的可能性,而不是所有应该共享相同属性内容的不同对象随之改变。如果我弄错了,请告诉我,我会删除我的答案,因为以下是基于这个假设。
使用基类或接口解决问题。它只是确保两者都具有相同名称的属性。如果可能的话。我会尝试实现不同的模式。
这样做的一种方法是,您可以创建一个在Country
对象和State
对象中都有引用的对象。比创建一个对象,调用它Controller
来控制Name
对象的内容。如果名称必须更改,则调用控制器并相应地更改内容。确保将Country
对象和State
对象上的属性设置为Readonly
。
更简单但同样有效的方法是创建一个'Controller',它是唯一可以更改属性的对象。两个属性之间不需要引用。如果控制器是唯一可以更改属性的对象,则在控制器上创建一个方法,将United States
的名称更改为US
。如果控制器知道所有国家/地区的集合,则可以通过查找原始内容并将其更改为新内容来更改属性。如果有两个控制器,一个用于国家,一个用于状态,它可以调用另一个控制器上的方法进行相同的更改。 (可以使用接口或基类强制存在这种更改方法)
这样想。椅子上有一组腿,但椅子本身并不知道这一点。它只是一把椅子。它是椅子的用户或所有者,知道它有4条腿。它也可以有三条腿。如果腿断了,你就告诉木匠修理椅子的腿。如果你想在三条腿的椅子上增加额外的腿,你可以告诉木匠而不是椅子。在您的情况下,如果更改国家/地区的名称,请将其告知国家/地区控制器。然后国家名称被更改。这个国家本身就有一个名字。
这个解决方案的问题在于,在一个已经拥有大量代码库的项目中,许多人已经开始研究这个问题,只是介绍了另一种做事方式。旧代码可能不会遵循新的处理方式,这使得代码的其余部分变得很奇怪。此外,大多数时候重构整个代码库是不可行的,也是不可取的。当然,慢慢引入这种新方式可能是一种选择。