我有三种重复代码的方法。 前两种方法几乎完全重复。第三个与火灾略有不同,应该绘制更多的信息。
我想删除这个重复的代码,并考虑使用内部类的模板方法模式。这是正确的方法还是有更好的解决方案?
private void drawWaterSupplies(Graphics g) {
double hScale = getWidth() / (double) groundMap.getWidth();
double vScale = getHeight() / (double) groundMap.getHeight();
int imageOffsetX = waterSupplyImage.getWidth() / 2;
int imageOffsetY = waterSupplyImage.getHeight() / 2;
for (Location l : groundMap.getWaterSupplyLocations()) {
int x = (int) (l.getX() * hScale);
int y = (int) (l.getY() * vScale);
g.drawImage(waterSupplyImage, x - imageOffsetX, y - imageOffsetY,
null);
}
}
private void drawEnergySupplies(Graphics g) {
double hScale = getWidth() / (double) groundMap.getWidth();
double vScale = getHeight() / (double) groundMap.getHeight();
int imageOffsetX = energySupplyImage.getWidth() / 2;
int imageOffsetY = energySupplyImage.getHeight() / 2;
for (Location l : groundMap.getEnergySupplyLocations()) {
int x = (int) (l.getX() * hScale);
int y = (int) (l.getY() * vScale);
g.drawImage(energySupplyImage, x - imageOffsetX, y - imageOffsetY,
null);
}
}
private void drawFires(Graphics g) {
double hScale = getWidth() / (double) groundMap.getWidth();
double vScale = getHeight() / (double) groundMap.getHeight();
int imageOffsetX = fireImage.getWidth() / 2;
int imageOffsetY = fireImage.getHeight() / 2;
for (Fire fire : groundMap.getFires()) {
Location l = fire.getLocation();
int x = (int) (l.getX() * hScale);
int y = (int) (l.getY() * vScale);
g.drawImage(fireImage, x - imageOffsetX, y - imageOffsetY, null);
// TODO: draw status bar showing state of fire below
}
}
答案 0 :(得分:5)
在我看来,你的对象集合(Fire
,WaterSupply
等)并不像它们应该的那样聪明。理想情况下,您应该能够说:
for (Fire f : groundMap.getFires()) {
f.draw(g);
}
并且每个对象都能够定位自己(使用其位置),大小本身(因为Fire
知道它将使用FireImage
等)并将自己绘制到提供的Graphics对象上。
为了更进一步,我希望将Graphics
对象传递给你的groundMap:
groundMap.drawFires(g);
这个想法是在OO中你不应该向对象询问他们的细节然后做出决定。 相反,你应该告诉对象为你做事。
答案 1 :(得分:1)
我会委托另一种方法为火,水和能源创建一个超类。
这个超级类将包含所有常见属性。例如getLocation()
例如
private void drawEverything(Graphics g, Image im, List<? extends SuperClassOfFireEtc> list, double w, double h) {
double hScale = getWidth() / w;
double vScale = getHeight() / h;
int imageOffsetX = im.getWidth() / 2;
int imageOffsetY = im.getHeight() / 2;
for (SuperClassOfFireEtc f : list) {
Location l = f.getLocation();
int x = (int) (l.getX() * hScale);
int y = (int) (l.getY() * vScale);
g.drawImage(im, x - imageOffsetX, y - imageOffsetY, null);
}
}
然后drawFire可以调用
private void drawEverything(g, fireImage, groundMap.getFires(), groundMap.getWidth(), groundMap.getHeight()) {
答案 2 :(得分:1)
怎么样:
private void drawImageAtLocations(Graphics g, Image i, Collection<Location> cl) {
double hScale = getWidth() / (double) groundMap.getWidth();
double vScale = getHeight() / (double) groundMap.getHeight();
int imageOffsetX = i.getWidth() / 2;
int imageOffsetY = i.getHeight() / 2;
for (Location l : cl) {
int x = (int) (l.getX() * hScale);
int y = (int) (l.getY() * vScale);
g.drawImage(i, x - imageOffsetX, y - imageOffsetY, null);
}
}
开箱即用于前两个:
drawImageAtLocations(g, waterSupplyImage, groundMap.getWaterSupplyLocations());
drawImageAtLocations(g, energySupplyImage, groundMap.getEnergySupplyLocations());
第三个有点麻烦,但仍然比原来的更短:
Set<Location> derp = new HashSet<Location>();
for (Fire fire : groundMap.getFires()) derp.add(fire.getLocation());
drawImageAtLocations(g, fireImage, derp);
// drawImageAtLocations(g, fireStatusBarImage, derp); // TODO blah blah
答案 3 :(得分:0)
首先,您似乎可以拥有一个接收Graphics
,List<Location>
和图像的常用方法,因此第一个和第二个方法可以提取该列表并进行调用。
第三种方法可以提取Fire列表,然后创建相应的List<Location>
。然后使用新方法。
private void drawImages(Graphics g, List<Location> where, Image imageToDraw) {
...
}
答案 4 :(得分:0)
我认为一个简单的解决方案是使用一个方法并传递Graphics和Location的集合。
答案 5 :(得分:0)
你可以有一个方法。
private void drawImageAtLocations(Graphics g, Image image, List<Location> locations) {
double hScale = getWidth() / (double) groundMap.getWidth();
double vScale = getHeight() / (double) groundMap.getHeight();
int imageOffsetX = image.getWidth() / 2;
int imageOffsetY = image.getHeight() / 2;
for (Location l : locations) {
int x = (int) (l.getX() * hScale);
int y = (int) (l.getY() * vScale);
g.drawImage(image, x - imageOffsetX, y - imageOffsetY, null);
}
}
private void drawWaterSupplies(Graphics g) {
drawImageAtLocations(g, waterSupplyImage, groundMap.getWaterSupplyLocations());
}
答案 6 :(得分:0)
这就是我的主张
enum Supplies {FIRE(fireImage), WATER(waterImage), ENERGY(energyImage);
private Bitmap image;
Supplies(Bitmap image)
{
this.image = image
}
public getImage()
{
return image;
}
}
private void draw(Graphics g,Supplies supply) {
double hScale = getWidth() / (double) groundMap.getWidth();
double vScale = getHeight() / (double) groundMap.getHeight();
int imageOffsetX = supply.getImage.getWidth() / 2;
int imageOffsetY = supply.getImage.getHeight() / 2;
for (Location location : groundMap.getLocations(supply)) {
int x = (int) (location .getX() * hScale);
int y = (int) (location .getY() * vScale);
g.drawImage(supply.getImage, x - imageOffsetX, y - imageOffsetY, null);
}
}
.... 您可以在地图&gt;中保存的所有火灾,水,能源等位置,因此方法getLocations(供应)或多或少看起来像那样
List<Location> getLocations(Supplies supply)
{
return supplyMap.get(supply);
}
如果您想添加或删除耗材和事故,此解决方案可为您提供更大的灵活性
答案 7 :(得分:0)
不是最短的选择,但它使代码更干净,更容易扩展:
enum YourEnum {
WATER,
ENERGY,
FIRE;
}
private void draw(Graphics g, YourEnum type) {
Bitmap bitmap = getRightBitmap(type);
double hScale = getWidth() / (double)groundMap.getWidth();
double vScale = getHeight() / (double)groundMap.getHeight();
int imageOffsetX = bitmap.getWidth() / 2;
int imageOffsetY = bitmap.getHeight() / 2;
for (Location l : getLocations(type)) {
int x = (int)(l.getX() * hScale);
int y = (int)(l.getY() * vScale);
g.drawImage(bitmap, x - imageOffsetX, y - imageOffsetY,
null);
}
}
private Bitmap getRightBitmap(YourEnum type) {
switch (type) {
case WATER:
return waterSupplyImage;
case ENERGY:
return waterSupplyImage;
case FIRE:
return fireImage;
}
}
private Collection<Location> getLocations(YourEnum type) {
switch (type) {
case WATER:
return groundMap.getWaterSupplyLocations();
case ENERGY:
return groundMap.getEnergySupCollections();
case FIRE:
Collection<Location> locations = new ArrayList<Location>();
for (Fire fire : groundMap.getFires()) {
locations.add(fire.getLocation());
}
return locations;
}
}