jeudi 19 juillet 2018

Separating types returned by Strategy pattern

I'm having a problem with some code. To try and get to the point, I cooked up an analogy as simple as possible - please excuse any syntax error, as I'm rusty when it comes to programming and I put this together rather quickly.

The idea is that I have some classes that implement a strategy. I need the object that manages them to somehow recognize the type returned by an operation in order to handle it (possibly without downcasting) - don't ask, this is not under my control.

I thought about using covariant return types to avoid having to explicitly refer to the concrete implementations (even though then I have to write a function that handles each type, but it seems ok to me as everything is kept together and for a new type you just add a new function).

    public abstract class ArtPiece
{
}

public class Painting extends ArtPiece
{
    public Painting()
    {
    }

    // paintings stuff here
}

public class Song extends ArtPiece
{
    public Song()
    {
    }

    // songs stuff here
}

public class Book extends ArtPiece
{
    public Book()
    {
    }

    // books stuff here
}

///////////////////////////////////////////////////

public abstract class Artist
{
    public abstract ArtPiece create();
}

public class Painter extends Artist
{
    public Painter()
    {
    }

    public Painting create()
    {
        return new Painting();
    }
}

public class Musician extends Artist
{
    public Musician()
    {
    }

    public Song create()
    {
        return new Song();
    }
}

public class Writer extends Artist
{
    public Writer()
    {
    }

    public Book create()
    {
        return new Book();
    }
}

//////////////////////////////////////////////////

public class ArtCollector
{
    private Artist[] artists;
    private Painting[] paintings;
    private Song[] songs;
    private Book[] books;

    private int followedArtists;
    private int ownedPaintings;
    private int ownedSongs;
    private int ownedBooks;

    public ArtCollector()
    {
        followedArtists = 0;
        ownedPaintings = 0;
        ownedSongs = 0;
        ownedBooks = 0;

        artists = new Artist[3];
        paintings = new Painting[3];
        songs = new Song[3];
        books = new Book[3];
    }

    public void followArtist(Artist a)
    {
        if (followedArtists < artists.length)
        {
            artists[followedArtists++] = a;
            return;
        }
        System.out.println("Too many artists to follow!");
    }

    public void commissionArt(int id)
    {
        storeArtPiece(artists[id].create());
    }

    private void storeArtPiece(Painting p)
    {
        if (ownedPaintings < paintings.length)
        {
            paintings[ownedPaintings++] = p;
            return;
        }
        System.out.println("Too many paintings to store!");
    }

    private void storeArtPiece(Song s)
    {
        if (ownedSongs < songs.length)
        {
            songs[ownedSongs++] = s;
            return;
        }
        System.out.println("Too many songs to store!");
    }

    private void storeArtPiece(Book b)
    {
        if (ownedBooks < books.length)
        {
            books[ownedBooks++] = b;
            return;
        }
        System.out.println("Too many books to store!");
    }

    public void countPaintings()
    {
        System.out.println("I own " + paintings.length.toString() + " paintings.");
    }

    public void countSongs()
    {
        System.out.println("I own " + songs.length.toString() + " songs.");
    }

    public void countBooks()
    {
        System.out.println("I own " + books.length.toString() + " books.");
    }
}

//////////////////////////////////////////////////

public static void main(string[] args)
{
    ArtCollector collector = new ArtCollector();

    collector.followArtist(new Musician());
    collector.followArtist(new Painter());
    collector.followArtist(new Writer());

    collector.commissionArt(0);
    collector.commissionArt(0);
    collector.commissionArt(1);
    collector.commissionArt(2);
    collector.commissionArt(1);
    collector.commissionArt(0);
    collector.commissionArt(0);

    collector.countPaintings();
    collector.countSongs();
    collector.countBooks();
}

First of all, I haven't tested this approach. It's just an idea I had to handle this problem. I'd like to know your opinion about it - am I on the right track? Do you think there is a better way to handle this?

Thank you!

Aucun commentaire:

Enregistrer un commentaire