gpt4 book ai didi

c# - 了解 C# 中的装饰器设计模式

转载 作者:IT王子 更新时间:2023-10-29 04:40:46 25 4
gpt4 key购买 nike

我刚开始学习装饰器设计模式,不幸的是我不得不通过各种引用资料才能更好地理解装饰器模式,这让我很困惑。所以,就我的理解而言,我相信这是一个装饰器模式

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();
}
}

但是下面的代码也可以是装饰器模式吗?

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();
}
}

我的理解

从我给出的第二个例子中,我们可以调用所有三个方法,但是从第一个例子中我将无法通过创建一个对象来访问所有三个方法。

最佳答案

应该是评论,但是我的话太多了。

例如,您有一个对象和接口(interface),如 Repository : IRepository

public interface IRepository
{
void SaveStuff();
}

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

和client,可能是别人写的

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

一旦您决定,应该记录对存储库的所有调用。但是您遇到了一个问题:Repository 类来自外部库,您不想更改该代码。因此,您需要扩展您使用的 Repository 的行为。您编写 RepositoryLogDecorator : IRepository,并在每个方法内部执行日志记录,例如

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
}
}

所以,在你可以使用客户端之前

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

但现在你可以使用

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

请注意,这是一个非常简单的示例。在实际项目中,对象主要使用 DI 容器创建,您将能够通过更改一些配置来使用装饰器。

因此,装饰器用于在不更改对象或客户端的情况下扩展对象的功能。

装饰器的另一个好处:您的装饰器不依赖于Repository 实现。仅依赖于接口(interface) IRepository。为什么这是一个优势?如果您决定以某种方式编写自己的 IRepository

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

您将能够使用已经存在的装饰器自动装饰它

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

想看真实软件的例子吗? (就像示例一样,代码很难看,我知道)=> go here

关于c# - 了解 C# 中的装饰器设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40294622/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com