装饰器模式帮助
我正在研究 Oreilly 的示例
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Collections.Generic;
using Given;
// Decorator Pattern Example Judith Bishop August 2007
// Draws a single photograph in a window of fixed size
// Has decorators that are BorderedPhotos and TaggedPhotos that can be composed and added
// in different combinations
namespace Given {
// The original Photo class
public class Photo : Form {
Image image;
public Photo () {
image = new Bitmap("jug.jpg");
this.Text = "Lemonade";
this.Paint += new PaintEventHandler(Drawer);
}
public virtual void Drawer(Object source, PaintEventArgs e) {
e.Graphics.DrawImage(image,30,20);
}
}
}
class DecoratorPatternExample {
// This simple BorderedPhoto decorator adds a colored BorderedPhoto of fixed size
class BorderedPhoto : Photo {
Photo photo;
Color color;
public BorderedPhoto (Photo p, Color c) {
photo = p;
color=c;
}
public override void Drawer(Object source, PaintEventArgs e) {
photo.Drawer(source, e);
e.Graphics.DrawRectangle(new Pen(color, 10),25,15,215,225);
}
}
// The TaggedPhoto decorator keeps track of the tag number which gives it
// a specific place to be written
class TaggedPhoto : Photo {
Photo photo;
string tag;
int number;
static int count;
List <string> tags = new List <string> ();
public TaggedPhoto(Photo p, string t) {
photo = p;
tag = t;
tags.Add(t);
number = ++count;
}
public override void Drawer(Object source, PaintEventArgs e) {
photo.Drawer(source,e);
e.Graphics.DrawString(tag,
new Font("Arial", 16),
new SolidBrush(Color.Black),
new PointF(80,100+number*20));
}
public string ListTaggedPhotos() {
string s = "Tags are: ";
foreach (string t in tags) s +=t+" ";
return s;
}
}
static void Main () {
// Application.Run acts as a simple client
Photo photo;
TaggedPhoto foodTaggedPhoto, colorTaggedPhoto, tag;
BorderedPhoto composition;
// Compose a photo with two TaggedPhotos and a blue BorderedPhoto
photo = new Photo();
Application.Run(photo);
foodTaggedPhoto = new TaggedPhoto (photo,"Food");
colorTaggedPhoto = new TaggedPhoto (foodTaggedPhoto,"Yellow");
composition = new BorderedPhoto(colorTaggedPhoto, Color.Blue);
Application.Run(composition);
Console.WriteLine(colorTaggedPhoto.ListTaggedPhotos());
// Compose a photo with one TaggedPhoto and a yellow BorderedPhoto
photo = new Photo();
tag = new TaggedPhoto (photo,"Jug");
composition = new BorderedPhoto(tag, Color.Yellow);
Application.Run(composition);
Console.WriteLine(tag.ListTaggedPhotos());
}
}
/* Output
TaggedPhotos are: Food Yellow
TaggedPhotos are: Food Yellow Jug
*/
,下一个练习是
假设 Photo 类是用 Drawer 作为普通(非虚拟)编写的 方法,并且不能改变。重构示例 2-2 使其能够工作 在这种限制下
我该怎么做?
我的方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using GivenWihInterface;
namespace GivenWihInterface
{
interface IPhoto
{
void Drawer(object sender, PaintEventArgs e);
}
class Photo : Form, IPhoto
{
Image image;
public Photo()
{
image = new Bitmap(@"c:\users\anishmarokey\documents\visual studio 2010\Projects\Design_Pattern_Decorator\DecoratorPattern_RealExample\Images\apple-6.jpg");
this.Text = "Apple";
this.Paint += new PaintEventHandler(Drawer);
}
public void Drawer(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(image, 20, 20);
}
}
class BorderPhoto : Form, IPhoto
{
IPhoto pho;
Color color;
public BorderPhoto(IPhoto p, Color c)
{
pho = p;
color = c;
this.Paint += new PaintEventHandler(Drawer);
}
public void Drawer(object sender, PaintEventArgs e)
{
pho.Drawer(sender, e);
e.Graphics.DrawRectangle(new Pen(color, 10), 25, 15, 215, 225);
}
}
}
namespace DecoratorPattern_RealExample
{
class DecoratorPatternWithInterface
{
static void Dispaly(GivenWihInterface.IPhoto p)
{
Application.Run((Form)p);
}
static void Main()
{
IPhoto component = new GivenWihInterface.Photo();
Dispaly(component);
component = new GivenWihInterface.Photo();
IPhoto p = new GivenWihInterface.BorderPhoto(component,Color.Red);
Application.Run((Form)p);
}
}
}
这是正确的方法吗?
I am working on an Oreilly's example
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Collections.Generic;
using Given;
// Decorator Pattern Example Judith Bishop August 2007
// Draws a single photograph in a window of fixed size
// Has decorators that are BorderedPhotos and TaggedPhotos that can be composed and added
// in different combinations
namespace Given {
// The original Photo class
public class Photo : Form {
Image image;
public Photo () {
image = new Bitmap("jug.jpg");
this.Text = "Lemonade";
this.Paint += new PaintEventHandler(Drawer);
}
public virtual void Drawer(Object source, PaintEventArgs e) {
e.Graphics.DrawImage(image,30,20);
}
}
}
class DecoratorPatternExample {
// This simple BorderedPhoto decorator adds a colored BorderedPhoto of fixed size
class BorderedPhoto : Photo {
Photo photo;
Color color;
public BorderedPhoto (Photo p, Color c) {
photo = p;
color=c;
}
public override void Drawer(Object source, PaintEventArgs e) {
photo.Drawer(source, e);
e.Graphics.DrawRectangle(new Pen(color, 10),25,15,215,225);
}
}
// The TaggedPhoto decorator keeps track of the tag number which gives it
// a specific place to be written
class TaggedPhoto : Photo {
Photo photo;
string tag;
int number;
static int count;
List <string> tags = new List <string> ();
public TaggedPhoto(Photo p, string t) {
photo = p;
tag = t;
tags.Add(t);
number = ++count;
}
public override void Drawer(Object source, PaintEventArgs e) {
photo.Drawer(source,e);
e.Graphics.DrawString(tag,
new Font("Arial", 16),
new SolidBrush(Color.Black),
new PointF(80,100+number*20));
}
public string ListTaggedPhotos() {
string s = "Tags are: ";
foreach (string t in tags) s +=t+" ";
return s;
}
}
static void Main () {
// Application.Run acts as a simple client
Photo photo;
TaggedPhoto foodTaggedPhoto, colorTaggedPhoto, tag;
BorderedPhoto composition;
// Compose a photo with two TaggedPhotos and a blue BorderedPhoto
photo = new Photo();
Application.Run(photo);
foodTaggedPhoto = new TaggedPhoto (photo,"Food");
colorTaggedPhoto = new TaggedPhoto (foodTaggedPhoto,"Yellow");
composition = new BorderedPhoto(colorTaggedPhoto, Color.Blue);
Application.Run(composition);
Console.WriteLine(colorTaggedPhoto.ListTaggedPhotos());
// Compose a photo with one TaggedPhoto and a yellow BorderedPhoto
photo = new Photo();
tag = new TaggedPhoto (photo,"Jug");
composition = new BorderedPhoto(tag, Color.Yellow);
Application.Run(composition);
Console.WriteLine(tag.ListTaggedPhotos());
}
}
/* Output
TaggedPhotos are: Food Yellow
TaggedPhotos are: Food Yellow Jug
*/
Next Exercise is
Assume that the Photo class was written with Drawer as a plain (not virtual)
method and it cannot be altered. Reconstruct Example 2-2 so that it works
under this constraint
How can i do that ?
My Approach
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using GivenWihInterface;
namespace GivenWihInterface
{
interface IPhoto
{
void Drawer(object sender, PaintEventArgs e);
}
class Photo : Form, IPhoto
{
Image image;
public Photo()
{
image = new Bitmap(@"c:\users\anishmarokey\documents\visual studio 2010\Projects\Design_Pattern_Decorator\DecoratorPattern_RealExample\Images\apple-6.jpg");
this.Text = "Apple";
this.Paint += new PaintEventHandler(Drawer);
}
public void Drawer(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(image, 20, 20);
}
}
class BorderPhoto : Form, IPhoto
{
IPhoto pho;
Color color;
public BorderPhoto(IPhoto p, Color c)
{
pho = p;
color = c;
this.Paint += new PaintEventHandler(Drawer);
}
public void Drawer(object sender, PaintEventArgs e)
{
pho.Drawer(sender, e);
e.Graphics.DrawRectangle(new Pen(color, 10), 25, 15, 215, 225);
}
}
}
namespace DecoratorPattern_RealExample
{
class DecoratorPatternWithInterface
{
static void Dispaly(GivenWihInterface.IPhoto p)
{
Application.Run((Form)p);
}
static void Main()
{
IPhoto component = new GivenWihInterface.Photo();
Dispaly(component);
component = new GivenWihInterface.Photo();
IPhoto p = new GivenWihInterface.BorderPhoto(component,Color.Red);
Application.Run((Form)p);
}
}
}
is this the correct Way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,这是一个适当的“装饰器”实现。我唯一疑问的是您是否真的需要从
Form
继承,或者实现IPhoto
是否足够。这只能通过更多背景来回答。另外,如果某些现有值在某处可用,则硬编码(尺寸?)值看起来可能有更好的方法。
不过,这个示例本身很不寻常 - 您必须引入界面,这几乎是您试图避免的变化;并且类型自行处理事件,这是不好的做法。我几乎想知道他们是否希望你加入事件管道,但这并不是真正的装饰器。
我怀疑他们希望您针对 Form 而不是您引入的 IPhoto 进行编码,这将允许您装饰很多东西。但是您需要在 Form 上有一个已知的方法来调用,例如 Paint() - 只不过这里是一个事件,而不是一个方法,因此名称会有所不同。我们可以再次挂钩该事件,但这不是经典的装饰器用法。
Yes, that is an appropriate "decorator" implementation. The only thing I'd question is whether you actually need to inherit from
Form
, or whether implementingIPhoto
is sufficient. Which can only be answered with more context.Also, the hard-coded (dimensions?) values look like there may be a better way if some existing values are available somewhere.
The example itself is unusual, though - you've had to introduce the interface, which is pretty much as much of a change as you are trying to avoid; and the type handles an event on itself, which is bad practice. I almost wonder if they want you to hook into the event pipeline, but that wouldn't really be a decorator.
I suspect they want you to code against Form rather than the IPhoto you have introduced, which would allow you to decorate lots of things. But you would need to have a known method on Form to call, for example Paint() - except that is an event here, not a method so the name will be different. And again we could hook the event, but that isn't classic decorator usage.