【问题标题】:Having issue with flyweight pattern享元模式有问题
【发布时间】:2016-05-04 00:35:32
【问题描述】:

当需要装箱大量特定类型的物体时,我们会使用享元。因为它们共享一个公共数据(内在状态),所以有助于减少内存消耗,并且还拥有自己的状态(外在状态),它不会在所有其他对象之间共享。这是一个示例代码

public abstract class Shape {

    private String color;
    private int x;
    private int y;

    public Shape(String color) {
        super();
        this.color = color;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public abstract String draw();

    @Override
    public String toString() {
        return "[color=" + color + ", x=" + x + ", y=" + y + "]";
    }


}


public class Circle extends Shape {

    public Circle(String color) {
        super(color);
    }

    @Override
    public String draw() {
        // TODO Auto-generated method stub
        return "Circle " + toString();
    }

}

import java.util.HashMap;

public class ShapeFactory {

    private static HashMap<String, Shape> circle_map = new HashMap<>();

    public static Shape getCircle(String size){
        if(!circle_map.containsKey(size))
            circle_map.put(size, new Circle(size));

        return circle_map.get(size);
    }

}

和司机

public class ShapeDriver {

    public static void main(String[] args) {

        Shape first_circle = ShapeFactory.getCircle("small");
        first_circle.setX(45);
        first_circle.setY(12);
        Shape second_circle = ShapeFactory.getCircle("small");

        System.out.println("First circle" + first_circle);
        System.out.println("Second circle" + second_circle);

        second_circle.setX(62);
        second_circle.setY(23);

        System.out.println("First circle" + first_circle);
        System.out.println("Second circle" + second_circle);
    }

}

在这个例子中,我希望大小是内在的,坐标(x,y)是外在的,但是当我改变 first_circle 的坐标时,它也反映了 second_circle 的变化,因为它们共享一个完整的对象而不是只是一个状态。输出如下

First circle[color=small, x=45, y=12]
Second circle[color=small, x=45, y=12]
First circle[color=small, x=62, y=23]
Second circle[color=small, x=62, y=23]

相当于创建一个对象并将其存储在不同的对象中,但它们都具有相同的状态或数据,那么它们如何拥有自己的数据(外部状态)?

【问题讨论】:

  • 请出示您的 ShapeFactory 的代码。
  • 你确定享元适合这个吗?您想创建许多具有不同状态(即坐标)的“圆形”对象。 Flyweight 将只能应用于共享状态(即颜色) - 您仍然必须拥有单独的“形状”实例才能将 flyweight 对象与可变状态连接。
  • 谢谢@sisyphus 我明白你的意思,我错了蝇量级。颜色是共享状态,那么享元应该只存储color,并且每次circle 的新对象都将使用相同的颜色对象创建,正如@Glenner003 所写。

标签: oop design-patterns flyweight-pattern


【解决方案1】:

享元对象应该是不可变的。

在您的示例中,您可以将重用部分(颜色/大小,您的示例冲突)放在一个单独的类中,并将其用作享元。

然后您将为每个位置实例化一个新的 Circle,但重复使用颜色对象。

public class Color {
     String color;
     public (String color) {
         this.color = color;
     }
     ...
}    

public abstract class Shape {

        private Color color;
        private int x;
        private int y;

        public Shape(Color color) {
            super();
            this.color = color;
        }
        ...    
    }


    public class Circle extends Shape {

        public Circle(Color color) {
            super(Color);
        }

         ...    
    }


    public class ShapeFactory {

        private static HashMap<String, Color> color_map = new HashMap<>();

        public static Shape getCircle(String color){
            if(!color_map.containsKey(color))
                color_map .put(color, new Color(color));

            return new Circle(color_map.get(size));
        }

    }

【讨论】:

  • 您能否引用声明的来源,“享元对象应该是不可变的”?我同意你的看法;但我很好奇这是你读过的东西,还是只是一个意见。
  • 谢谢@Glenner003,现在我明白flyweight应该只处理(存储)共享对象,在我们的例子中是color,并且每次都应该创建circle的新对象和共享color目的。我在关注this 的例子,你能看看这个吗?我认为那是错误的。
  • @jaco0646 我可能曾经在某个地方读过它,但我不记得在哪里。然而,维基百科确实证实了这一点:en.wikipedia.org/wiki/…
  • @user464 实际上,是否会将圆圈放入列表中并在创建所有圆圈后绘制,特定颜色的每个圆圈将共享相同的坐标。
  • 谢谢@jaco0646 你能在this 上看到我关注的文章,我认为他们做错了。
猜你喜欢
  • 1970-01-01
  • 2014-07-04
  • 1970-01-01
  • 2013-12-27
  • 1970-01-01
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
  • 2018-03-01
相关资源
最近更新 更多