miiworld2 miiworld2 - 1 month ago 6
C# Question

C# decorator pattern and wrapping issues

I am having a problem wrapping my code return values. So basically I am trying to display the following output:


Morg, type, xy, paddle


My code is in C#, and based on my code below, these outputs are based on my return values which are in string. I'm using them in hope to test my program to see if it works. Well so far it works but not the way I want. I only get to display the type return value, but I can't seem to display the rest of it.

This is what it gives me.


type


But the one at the very top is the one I want to display as output. Not just the type.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
MorgReader myMorg = new FileReader();
MorgReader myMorg2 = new MorgType(new MorgXY(new MorgMovement(new FileReader())));

Console.WriteLine(myMorg.Read());
Console.WriteLine(myMorg2.Read());

}

}

// THE MAIN ABSTRACT CLASS //
abstract class MorgReader
{
public abstract string Read();
}

// THE CLASS THAT WILL READ THE FILE //
class FileReader : MorgReader
{
public override string Read()
{
return "Morg";
}
}

// MY READER DECORATOR //

abstract class ReaderDecorator : MorgReader
{
private MorgReader wrappedReader;
protected ReaderDecorator(MorgReader wrapped)
{
wrappedReader = wrapped;
}
protected MorgReader WrappedReader
{ get { return wrappedReader; } }
}

class MorgType : ReaderDecorator
{
public MorgType(MorgReader wrapped) : base(wrapped)
{ }

public override string Read()
{
return "type";
}
}

class MorgXY : ReaderDecorator
{
public MorgXY(MorgReader wrapped) : base(wrapped)
{ }

public override string Read()
{
return "x,y";
}
}

class MorgMovement : ReaderDecorator
{
public MorgMovement(MorgReader wrapped) : base(wrapped)
{ }

public override string Read()
{
return "paddle";
}
}
}

Answer

Change your ReaderDecorator class

abstract class ReaderDecorator : MorgReader
{
    private MorgReader wrappedReader;
    protected ReaderDecorator(MorgReader wrapped)
    {
        wrappedReader = wrapped;
    }

    protected MorgReader WrappedReader
    { get { return wrappedReader; } }

    public override string Read()
    {
        var wrapped = WrappedReader.Read();
        if (!string.IsNullOrEmpty(wrapped))
            wrapped += ", ";

        return wrapped + ReadImpl();
    }

    // template method
    protected abstract string ReadImpl();
}

Implement ReadImpl in concrete class like this

class MorgType : ReaderDecorator
{
    public MorgType(MorgReader wrapped) : base(wrapped)
    { }

    protected override string ReadImpl()
    {
        return "type";
    }
}

If you don't want to introduce ReadImpl method, then you should override Read method in every concrete class like this

public override string Read()
{
    var wrapped = WrappedReader.Read();
    if (!string.IsNullOrEmpty(wrapped))
        wrapped += ", ";

    return wrapped + "type";
}