3

コードが重複しているメソッドが 3 つあります。最初の 2 つの方法はほぼ完全に重複しています。3 番目のものは少し異なり、火災についてはより多くの情報を描画する必要があります。

この重複コードをなくしたくて、インナークラスを使ったテンプレートメソッドのパターンを考えました。これは正しい方法ですか、それともより良い解決策がありますか?

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
    }
}
4

8 に答える 8

5

あなたのオブジェクト ( など) のコレクションはFireWaterSupply本来あるべきほど賢くないようです。理想的には、次のように言えるはずです。

for (Fire f : groundMap.getFires()) {
   f.draw(g);
}

そして、各オブジェクトは (その場所を使用して) 自分自身を見つけ、(aFireが a などを使用することを知っているため) 自分自身をサイズ設定FireImageし、提供された Graphics オブジェクトに自分自身を描画することができます。

これをさらに進めるために、次のようにGraphicsオブジェクトを GroundMapに渡すことを期待します。

groundMap.drawFires(g);

オブジェクト指向では、オブジェクトに詳細を尋ねてから決定を下すべきではないという考えです。代わりに、オブジェクトに何かを行うように指示する必要があります

于 2012-10-02T13:05:44.977 に答える
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()) {
于 2012-10-02T13:05:46.133 に答える
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);
    }
}

最初の 2 つはそのまま使用できます。

drawImageAtLocations(g, waterSupplyImage, groundMap.getWaterSupplyLocations());
drawImageAtLocations(g, energySupplyImage, groundMap.getEnergySupplyLocations());

3 番目のものは少し乱雑ですが、元のものよりも短いものです。

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
于 2012-10-02T13:14:31.247 に答える
0

Graphicsまず、 、 a 、および画像を受け取る共通のメソッドを使用できるように思われるList<Location>ため、最初と 2 番目のメソッドでそのリストを抽出して呼び出すことができます。

3 番目の方法では、Fire のリストを抽出し、対応する を作成できますList<Location>。次に、新しい方法を使用します。

private void drawImages(Graphics g, List<Location> where, Image imageToDraw) {
...
}
于 2012-10-02T13:06:06.863 に答える
0

簡単な解決策は、1 つのメソッドを持ち、Graphics と Location のコレクションを渡すことだと思います。

于 2012-10-02T13:06:56.993 に答える
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());
}
于 2012-10-02T13:07:11.330 に答える
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;
    }
}
于 2012-10-02T13:21:56.690 に答える
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);
    }
}

.... 火、水、エネルギーなどのすべての場所を Map> で保持できるため、メソッド getLocations(supply) は多かれ少なかれそのようになります

List<Location> getLocations(Supplies supply)
{
return supplyMap.get(supply);
}

このソリューションにより、消耗品や事故を追加または削除する場合の柔軟性が向上します

于 2012-10-02T13:19:56.813 に答える