1

好吧,我使用了一种构图模式,其中一个图形对象以一组和矩形的形式扩展。一个组可以有许多矩形,并且为这些组调用一个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);

在第五行,您可以看到我在将矩形添加到组之前将其放在装饰器中的位置,所以我应该使用反射并在添加到组的每个矩形上使用它们。还是有更好的方法来做到这一点?

还是我在这里使用装饰器的方式总体上是完全错误的?

提前致谢。

编辑:

以下是我的绘画方法在组中的实现方式:

public void draw(Graphics g, AlignStrategy align) {
    for (GraphicObject graphic: children) {
        graphic.draw(g, align);
    }
}

该组只调用儿童的绘制方法。

问题是,在我看来,装饰器应该是通用的,根据你给出的建议,它似乎会让它变得依赖?我的意思是该组基本上依赖于对齐?如果说我创建了一个可以旋转对象的装饰器,或者用 y 切换坐标 x 怎么办?我的意思不是关于左对齐、右对齐或居中对齐,而是关于装饰器的工作,而不必使代码过多地适应装饰器?

4

1 回答 1

1

如果您可以完全控制GraphicObject, Group,Rectangle等后面的代码(即,如果它是您的全部代码),那么我认为使用装饰器模式可能是困难的方法。使用类似于 AWTLayout方法的代码来实现绘图对齐会更简单,其中父对象(Group在您的情况下可能是 a )被赋予一个Layout负责管理父子对象排列的对象。默认布局不会影响子级。“左对齐”和“右对齐”布局将在绘制前一段时间发生的布局阶段对子项进行必要的位置更改。GroupLayout

如果您无法控制绘图对象背后的代码,那么我认为周围的装饰器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.
于 2012-09-29T19:53:10.090 回答