使用多态性传递价值对象不好的做法? [英] Is passing around value objects using polymorphism a bad practice?

查看:209
本文介绍了使用多态性传递价值对象不好的做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public interface IRecord
{

}

public class BirthRecord : IRecord
{
    public string CityOfBirth;
    public Date DateOfBirth;
    public BirthRecord(string cityOfBirth, Date dateOfBirth)
    {
        // assign these to properties
    }
}

public class CarRecord : IRecord
{
    public Color Color;
    public string Manufacturer;
    public CarRecord(Color color, string manufacturer)
    {
        // assign these to properties
    }
}

public interface IAccount
{
    public List<IRecord> Records { get; set; }
}

public class Client
{
    public void ProcessAccount(IAccount account)
    {
        foreach(IRecord record in account.Records)
        {
            if(record is CarRecord)
                handleCarRecord((CarRecord)record);
            else if(record is BirthRecord)
                handleBirthRecord((BirthRecord)record);
        }
    }
}

所以当你到达客户端并且想要处理你必须做各种各样的凌乱类型检查和投射的值对象 - 这是一个可以接受的模式,还是我做出更基本的设计错误?如果不是其他OOD原则,这似乎违反了OCP。有没有其他选择?

So when you get to the client and want to handle the value objects you have to do all kinds of messy type checking and casting- is this an acceptable pattern or am I making a more fundamental design mistake? This seems to violate OCP if not other OOD principles. Are there any alternatives?

推荐答案

您所呈现的方法称为访问者模式,但是访问者用于创建复杂的抽象算法数据结构,以便您有一个模板算法,并提供一个具体的实现。

The approach you present is called the Visitor Pattern however the Visitor is used to create abstract algorithms over complex data structures so that you have a template algorithm and just provide a concrete implementation of it.

public abstract class AbstractAccountVisitor {     

  public void ProcessAccount(IAccount account)     
  {          
     foreach(IRecord record in account.Records)         
     {             
         if(record is CarRecord)                 
             handleCarRecord((CarRecord)record);             
         else if(record is BirthRecord)                 
             handleBirthRecord((BirthRecord)record);         
     }     
  } 

  public abstract void handleCarRecord( CarRecord record );
  public abstract void handleBirthRecord( BirthRecord record );

} 

它允许你有

public class ConcreteAccountVisitor : AbstractAccountVisitor {

    public override handleCarRecord( CarRecord record ) {
       // do something concrete with carrecord
    }

    public override handleBirthRecord( BirthRecord record ) {
       // do something concrete with birthrecord
    }

}

// client
AbstractAccountVisitor visitor = new ConcreteAccountVisitor();

visitor.ProcessAccount( account );

请注意,通过将算法的核心封装在基本访问者中,您可以通过简单地自定义处理要处理特定类型的记录的重写方法。

Note that by encapsulating the core of the algorithm in the base visitor, you allow to customize processing by just overriding methods which process specific types of records.

还需要注意的是,您可以将处理内容介绍给您的课程:

Note also that instead of providing a visitor, you can just introduce the processing to your class:

public interface IRecord {
    void Operation();
}            

public class AccountProcessor {     

  public void ProcessAccount(IAccount account)     
  {          
     foreach(IRecord record in account.Records)         
     {             
         record.Operation();
     }     
  } 
} 

您的对象可能的操作列表是已知的,以便您可以在界面的合同中引入所有操作。另一方面,访问者可以在您提供新的具体访问者时,在课堂/界面上引入任意数量的操作。

Such easier approach is recommended when the list of possible operations on your objects is known so that you can introduce all operations in interface's contract. On the other hand, a visitor allows you to introduce an arbitrary number of operations on your class/interface as you just provide new concrete visitors.

这篇关于使用多态性传递价值对象不好的做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆