[英]Using the decorator pattern on this composition
好吧,我使用了一種合成模式,其中一個圖形對象在一組和矩形中擴展。 一個組可以有多個矩形,並且可以為組調用paint()方法,在矩形中調用paint方法,每個矩形都會繪制自己。
現在,我需要以某種方式使用裝飾器圖案,以將矩形對齊到左側或右側。 現在,如果我在組上使用裝飾器,它只會對齊我猜到的組坐標,但是由於所有矩形均會自己繪制,因此對它們沒有影響。
那么有什么想法可以在這里使用裝飾器模式嗎?
我的意思是,我想到使用它的唯一方法是在每個矩形和組中需要對齊的每個元素周圍使用裝飾器包裝器。 但這不違反裝飾器模式的政策嗎? 我的意思是從技術上講該組不知道列表中有什么,對它們來說,它們只是GraphicObject實例,而矩形不知道它們被裝飾器包裹着,裝飾器會在調用矩形的paint之前修改其坐標( ) 方法。
如果那是唯一的方法,那我怎么用它來裝飾那些物品呢? 我必須在這里使用反射還是有其他/更正確的方法來做到這一點?
一些代碼:
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怎么辦? 我的意思是這與對齊左,右或中心無關,而是與裝飾器工作而不必使代碼過多地適應裝飾器有關?
如果您完全控制GraphicObject
, Group
, Rectangle
等之類的代碼(即,如果這是您的全部代碼),那么我認為使用裝飾器模式可能很難。 使用類似於AWT的Layout
方法的代碼來實現圖形對齊會更簡單,在該方法中,為父對象(在您的情況下可能是Group
)分配了一個Layout
對象,該對象負責管理父子對象的排列。 默認布局不會影響子級。 “左對齊”和“右對齊”布局將在繪畫之前一段時間的布局階段對子項進行必要的位置更改。 因此, Group
將具有一個默認的Layout
對象,可以在需要它們時將其替換為特定於路線的版本。
如果您無法控制圖形對象背后的代碼,那么我認為Group
周圍的裝飾器要比裝飾所有子代更好。 讓Group
級別裝飾器的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.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.