Example with Visitor Pattern

2020-07-07 04:16发布

问题:

public class Song {
    public string Genre { get; protected set; }
    public string Name { get; protected set; }
    public string Band { get; protected set; }

    public Song(string name, string band, string genre) {
        Name = name;
        Genre = genre;
        Band = band;
    }
}

public interface IMusicVisistor
{
    void Visit(List<Song> items);
}

public class MusicLibrary {
    List<Song> _songs = new List<Song> { ...songs ... };

    public void Accept(IMusicVisitor visitor) {
        visitor.Visit(_songs);
    }
}

and now here's one Visitor I made:

public class RockMusicVisitor : IMusicVisitor {
    public List<Song> Songs { get; protected set; }

    public void Visit(List<Song> items) {
        Songs = items.Where(x => x.Genre == "Rock").ToList();
    }
}

Why is this any better than just putting a public property Songs and then letting any kind of class do with it anything that it wants to?

This example comes from this post.

回答1:

It is mainly because the example is a bad example of the visitor pattern. The purpose of the visitor pattern is to add common functionality to a group of objects without having to derive from the same class. It lets you keep adding functionality to classes without having to change the classes themselves. The longer fruit example in the answer that you quoted is a better explanation of the visitor pattern.

Read the quoted wikipedia article, for the visitor to pay off you should have a group of classes. In you case different classes are not really warranted so there is no need for the visitor pattern. Given a more heterogeneous class structure the visitor pattern might become useful.



回答2:

In my opinion, this pattern's usefulness has to do with the implementation of MusicLibrary. As shown above in it's most simple form, it's just passing in the list of songs into the Visitor.Visit method. In a more complex application there might not be an in-memory list to expose: for example it might have to scour the libraries of different machines just to build up the list. My point - however badly made - is that as the complexity of iterating Songs increases, that logic can be kept centrally in the MusicLibrary, and IMusicVisitor objects can just deal with collections of Songs.