Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
80 views
in Technique[技术] by (71.8m points)

Understanding Decorator Design Pattern in C#

I just started to learn Decorator Design Pattern, unfortunately i had to go through various refrences to understand the Decorator pattern in a better manner which led me in great confusion. so, as far as my understanding is concern, i believe this is a decorator pattern

interface IComponent
{
    void Operation();
}
class Component : IComponent
{
    public void Operation()
    {
        Console.WriteLine("I am walking ");
    }
}
class DecoratorA : IComponent
{
    IComponent component;
    public DecoratorA(IComponent c)
    {
        component = c;
    }
    public void Operation()
    {
        component.Operation();
        Console.WriteLine("in the rain");
    }
}
class DecoratorB : IComponent
{
    IComponent component;
    public DecoratorB(IComponent c)
    {
        component = c;
    }
    public void Operation()
    {
        component.Operation();
        Console.WriteLine("with an umbrella");
    }
}
class Client
{
    static void Main()
    {
        IComponent component = new Component();
        component.Operation();

        DecoratorA decoratorA = new DecoratorA(new Component());
        component.Operation();

        DecoratorB decoratorB = new DecoratorB(new Component());
        component.Operation();

        Console.Read();
    }
 }

But can the below code also be Decorator Pattern?

class Photo
{
    public void Draw()
    {
        Console.WriteLine("draw a photo");
    }
}
class BorderedPhoto : Photo
{
    public void drawBorder()
    {
        Console.WriteLine("draw a border photo");
    }
}
class FramePhoto : BorderedPhoto
{
    public void frame()
    {
        Console.WriteLine("frame the photo");
    }
}
class Client
{
    static void Main()
    {
        Photo p = new Photo();
        p.Draw();

        BorderedPhoto b = new BorderedPhoto();
        b.Draw();
        b.drawBorder();

        FramePhoto f = new FramePhoto();
        f.Draw();
        f.drawBorder();
        f.frame();
    }
}

My Understanding

From the second example given by me, we can call all the three methods, but from the first example i wont be able to get access to all the three methods by creating a single object.

question from:https://stackoverflow.com/questions/65862802/c-sharp-decorator-pattern-multiple-properties-wrapping-multiple-times

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It should be a comment, but I have too many words.

For example, you have an object and interface, like Repository : IRepository.

public interface IRepository
{
    void SaveStuff();
}

public class Repository : IRepository
{
    public void SaveStuff()
    {
        // save stuff   
    }
}

and client, which probably was written by someone else

class RepoClient
{
    public void DoSomething(IRepository repo)
    {
        //...
        repo.SaveStuff();
    }
}

And once you decided, that ALL calls to repository should be logged. But you have a problem: the Repository class is from an external library and you don't want to change that code. So you need to extend the Repository's behavior that you use. You write RepositoryLogDecorator : IRepository, and inside on each method do the logging, like

public class RepositoryLogDecorator  : IRepository
{
    public IRepository _inner;

    public RepositoryLogDecorator(IRepository inner)
    {
        _inner = inner;
    }

    public void SaveStuff()
    {
        // log enter to method
        try
        {
            _inner.SaveStuff();
        }
        catch(Exception ex)
        {
            // log exception
        }       
        // log exit to method
    }
}

So, before you could use client as

var client = new RepoClient();
client.DoSomething(new Repository());

but now you can use

var client = new RepoClient();
client.DoSomething(new RepositoryLogDecorator(new Repository()));

Note, that this is a very simple example. In real projects, where object created primary with DI container, you will be able to use decorator by changing some config.

So, decorator is used to extend functionality of object without changing object or client.

Another benefit of decorator: your decorator does not depend on Repository implementation. Only depends from an interface IRepository. Why this is an advantage? If somehow you decide to write you own implementation of IRepository

public class MyAwesomeRepository : IRepository
{
    public void SaveStuff()
    {
        // save stuff, but AWESOME!
    }
}

you will be able to automatically decorate this with decorator, which already exist

var client = new RepoClient();
client.DoSomethig(new RepositoryLogDecorator(new MyAwesomeRepository()));

Want to see example from real software? (just as sample, code is ugly, I know) => go here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...