这个享元模式真的是一个享元模式吗?

3
这里有一篇我正在阅读的教程: http://www.tutorialspoint.com/design_pattern/flyweight_pattern.htm 下面是我认为不符合轻量级模式要求的代码:
public interface Shape {
   void draw();
}

public class Circle implements Shape {
   private String color;
   private int x;
   private int y;
   private int radius;

   public Circle(String color){
      this.color = color;       
   }

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

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

   public void setRadius(int radius) {
      this.radius = radius;
   }

   @Override
   public void draw() {
      System.out.println("Circle: Draw() [Color : " + color + ", x : " + x + ", y :" + y + ", radius :" + radius);
   }
}

import java.util.HashMap;

public class ShapeFactory {
   private static final HashMap<String, Shape> circleMap = new HashMap();

   public static Shape getCircle(String color) {
      Circle circle = (Circle)circleMap.get(color);

      if(circle == null) {
         circle = new Circle(color);
         circleMap.put(color, circle);
         System.out.println("Creating circle of color : " + color);
      }
      return circle;
   }
}

public class FlyweightPatternDemo {
   private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" };
   public static void main(String[] args) {

      for(int i=0; i < 20; ++i) {
         Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor());
         circle.setX(getRandomX());
         circle.setY(getRandomY());
         circle.setRadius(100);
         circle.draw();
      }
   }
   private static String getRandomColor() {
      return colors[(int)(Math.random()*colors.length)];
   }
   private static int getRandomX() {
      return (int)(Math.random()*100 );
   }
   private static int getRandomY() {
      return (int)(Math.random()*100);
   }
}

这似乎不是一个轻量级模式,因为根据维基百科的说法,“轻量级是通过与其他类似对象共享尽可能多的数据来最小化内存使用的对象”。换句话说,我看不到具有固有和外在数据的对象。在这里,我只能看到一个带有某种缓存系统的工厂。
有人能否演示这是否是轻量级模式?

3
请在您的问题中发布相关代码,而不是链接到它。 - K Erlandsson
添加了相关的代码 - user1883212
我认为如果颜色是另一个类,工厂缓存的是颜色而不是形状,那么它就是享元模式。 - user1883212
1
@user1883212 哎呀,这正是我想到的事情。但是在上下文中,“有意义”的是形状本身被缓存,因为Circle仅在立即作用域中使用(当它绘制自身时)。因此没有圆形实际上被“共享”到另一个上下文中,因为只有一个实例在使用中。(如果它们被*共享会很糟糕,因为它们具有可变状态。) - user2864740
2
你的困惑是完全可以理解的。这段代码显然试图演示享元模式,但它有缺陷(在我看来毫无意义),而且教程写得很差。(该网站上的其他教程看起来也类似。)我建议寻找其他资源,比如原始的GoF设计模式书籍或者Java中的设计模式 - Andrew Janke
Wikipedia文章也更加清晰。最终,Flyweight模式只是一种缓存类型,所以你的文章要点是正确的——它是一个带有缓存的工厂。 - dimo414
1个回答

2
当您通过ShapeFactory创建新圆时,如果已存在所需颜色的实例,则返回已创建的实例。这样,您可以重复使用已创建的Circle实例(它们与具有相同颜色的圆“共享”数据),并最小化内存消耗。
话虽如此,此代码存在一些问题。例如,Circle对象是可变的,因此如果您开始修改已创建的圆,则所有具有相同颜色的其他圆也将被修改。
而且它完全不安全线程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接