我使用了一个组合模式,其中一个图形对象以组和矩形的形式扩展。一个组可以有多个矩形,并且paint()方法调用组,调用矩形中的paint方法,每个矩形绘制自己。
现在我需要在上面使用一个装饰器模式,将矩形向左或向右对齐。现在如果我在组上使用装饰器,我猜它只是对齐了组的坐标,但是因为所有的矩形都是自己画的,所以它对它们没有影响。
那么有什么想法可以让我在这里使用装饰器模式吗?
我的意思是,我能想到的使用它的唯一方法就是使用装饰器包装器来包装需要对齐的每个矩形和组中的每个元素。但是这不是违背了装饰者模式的策略吗?我的意思是,从技术上讲,组不知道它的列表中有什么,对它来说,元素只是GraphicObject实例,矩形不知道它们被一个装饰器包裹着,这个装饰器会在调用矩形的画图()方法之前修改它们的坐标。
如果这是唯一的方法,那么我如何使用它来装饰这些项目呢?我必须在这里使用反射吗?还有没有其他/更正确的方法呢?
下面是一些代码:
if (mainGroup == null) {
mainGroup = new Group();
// first line
currentBounds = convertToBoundsForLine(x, y, width, lineHeight, 1);
//System.out.format("current bounds: x1=%d, y1=%d, x2=%d, y2=%d%n", currentBounds.getX(), currentBounds.getY(), currentBounds.getX2(), currentBounds.getY2());
GraphicObject rect1 = new Rectangle(currentBounds);
mainGroup.addChild(rect1);
// other lines...
// fifth line
currentBounds = convertToBoundsForLine(x, y, width, lineHeight, 5);
//System.out.format("current bounds: x1=%d, y1=%d, x2=%d, y2=%d%n", currentBounds.getX1(), currentBounds.getY1(), currentBounds.getX2(), currentBounds.getY2());
GraphicObject rect5 = new Rectangle(currentBounds);
// this is with the decorator wrapper around - should I use reflection here?
GraphicObject blabla = new DecoratorLeft(rect5);
mainGroup.addChild(blabla);好的,在第五行,你可以看到在将矩形添加到组之前,我将矩形放在装饰器中的什么位置,所以我应该使用反射,并在添加到组的每个矩形上使用它们。或者有更好的方法来做到这一点?
或者我在这里使用装饰器的方式总体上是完全错误的?
提前谢谢。
编辑:
下面是我的paint方法在组中的实现方式:
public void draw(Graphics g, AlignStrategy align) {
for (GraphicObject graphic: children) {
graphic.draw(g, align);
}
}组只调用孩子的draw方法。
问题是,在我看来,装饰器应该是通用的,根据你给出的建议,它似乎会让它变得依赖?我的意思是团队基本上是依赖于对齐的?假设我创建了一个可以旋转对象的装饰器,或者将x坐标与y坐标进行切换,会怎么样?我的意思是,这不是关于左对齐、右对齐或居中对齐,而是关于装饰器工作而不需要太多地调整代码来适应装饰器?
发布于 2012-09-30 03:53:10
如果你能完全控制GraphicObject、Group、Rectangle等类似代码(也就是说,如果这些都是你的代码),那么我认为使用装饰器模式可能很难。使用类似于AWT的Layout方法的代码实现绘图对齐会更简单,在这种方法中,父对象(在本例中可能是一个Group )被赋予一个Layout对象,该对象负责管理父对象的子对象的排列。默认布局不会影响子项。“左对齐”和“右对齐”布局将在绘制前一段时间的布局阶段对子对象进行必要的位置更改。因此,当您需要特定于路线的版本时,Group将具有一个默认的Layout对象,该对象可以被替换。
如果您无法控制绘图对象背后的代码,那么我认为围绕Group的装饰器将比装饰子对象更好。让Group-level装饰器的paint()方法在被调用时管理子对象的对齐方式。这样,每个Group只有一个装饰器,而不是每个可绘制对象有一个装饰器。这本质上是合并到装饰器类中的布局代码,但您可以始终中断布局代码并让装饰器调用它。
编辑:这是第二种情况的一个例子。为了简单起见,我只列出了必要的部分,而不是细节。
public class GroupDecorator extends GraphicObject { //or extends whatever is best
public GroupDecorator(Group wrappedGroup) {
myGroup = wrappedGroup;
}
public void paint() { //Assume this is your common paint() method
//note I'm making up the names here, since I don't know them
List groupsChildren = myGroup.getChildren();
//The type of alignment is stored somewhere in this object
//or is hard-coded. That's up to you. I'll assume it's stored somewhere...
if (isAlignedLeft()) {
//align all the children to the left here
} else if (isAlignedRight()){
//align all the children to the right here
} else {
//do nothing because no alignment is necessary
}
//call the wrapped Group's paint now. It will call its children's paint()s.
myGroup.paint();
//Unalign all the children here, if necessary, to put them back in
//their original state. How you implement that is up to you.
}
}
// Somewhere in your main code...
mainGroup = new Group();
//Decorate mainGroup now...
GroupDecorator decoratedGroup = new GroupDecorator(mainGroup);
//Configure decoratedGroup to align however you want.
// first line
GraphicObject rect1 = new Rectangle();
mainGroup.addChild(rect1);
// other lines...
// fifth line
GraphicObject rect5 = new Rectangle();
//Now use decoratedGroup now in place of mainGroup.https://stackoverflow.com/questions/12655056
复制相似问题