这个设计模式的名称是什么? (如果是一个)

时间:2013-11-20 15:31:06

标签: c# design-patterns

我有一个大班,我们称之为'国家'。它有各种属性,如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;}
}

这种模式的名称是什么(如果它是一个)?我想了解更多关于它...还有其他选择吗?

4 个答案:

答案 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条腿。它也可以有三条腿。如果腿断了,你就告诉木匠修理椅子的腿。如果你想在三条腿的椅子上增加额外的腿,你可以告诉木匠而不是椅子。在您的情况下,如果更改国家/地区的名称,请将其告知国家/地区控制器。然后国家名称被更改。这个国家本身就有一个名字。

这个解决方案的问题在于,在一个已经拥有大量代码库的项目中,许多人已经开始研究这个问题,只是介绍了另一种做事方式。旧代码可能不会遵循新的处理方式,这使得代码的其余部分变得很奇怪。此外,大多数时候重构整个代码库是不可行的,也是不可取的。当然,慢慢引入这种新方式可能是一种选择。