content: import java.util.*;
  
  // Flyweight - Stores INTRINSIC state only
  class AsteroidFlyweight {
      // Intrinsic properties (shared among asteroids of same type)
      private int length;          
      private int width;           
      private int weight;          
      private String color;       
      private String texture;      
      private String material;    
  
      public AsteroidFlyweight(int l, int w, int wt, String col, String tex, String mat) {
          this.length = l;
          this.width = w;
          this.weight = wt;
          this.color = col;
          this.texture = tex;
          this.material = mat;
      }
  
      public void render(int posX, int posY, int velocityX, int velocityY) {
          System.out.println("Rendering " + color + ", " + texture + ", " + material 
              + " asteroid at (" + posX + "," + posY 
              + ") Size: " + length + "x" + width
              + " Velocity: (" + velocityX + ", " 
              + velocityY + ")");
      }
  
      public static long getMemoryUsage() {
          return Integer.BYTES * 3 +            // length, width, weight
                  40 * 3;                       // Approximate string data
      }
  }
  
  // Flyweight Factory
  class AsteroidFactory {
      private static Map<String, AsteroidFlyweight> flyweights = new HashMap<>();
  
      public static AsteroidFlyweight getAsteroid(int length, int width, int weight, 
                                                  String color, String texture, String material) {
  
          String key = length + "_" + width + "_" + weight + "_" + color + "_" + texture + "_" + material;
  
          if (!flyweights.containsKey(key)) {
              flyweights.put(key, new AsteroidFlyweight(length, width, weight, color, texture, material));
          }
  
          return flyweights.get(key);
      }
  
      public static int getFlyweightCount() {
          return flyweights.size();
      }
  
      public static long getTotalFlyweightMemory() {
          return flyweights.size() * AsteroidFlyweight.getMemoryUsage();
      }
  
      public static void cleanup() {
          flyweights.clear();
      }
  }
  
  // Context - Stores EXTRINSIC state only
  class AsteroidContext {
      private AsteroidFlyweight flyweight;
      private int posX, posY; // 8 bytes (position)
      private int velocityX, velocityY; // 8 bytes (velocity)
  
      public AsteroidContext(AsteroidFlyweight fw, int posX, int posY, int velX, int velY) {
          this.flyweight = fw;
          this.posX = posX;
          this.posY = posY;
          this.velocityX = velX;
          this.velocityY = velY;
      }
  
      public void render() {
          flyweight.render(posX, posY, velocityX, velocityY);
      }
  
      public static long getMemoryUsage() {
          return 8 + Integer.BYTES * 4; // approximate pointer + ints
      }
  }
  
  class SpaceGameWithFlyweight {
      private List<AsteroidContext> asteroids = new ArrayList<>();
  
      public void spawnAsteroids(int count) {
          System.out.println("\n=== Spawning " + count + " asteroids ===");
  
          String[] colors = {"Red", "Blue", "Gray"};
          String[] textures = {"Rocky", "Metallic", "Icy"};
          String[] materials = {"Iron", "Stone", "Ice"};
          int[] sizes = {25, 35, 45};
  
          for (int i = 0; i < count; i++) {
              int type = i % 3;
  
              AsteroidFlyweight flyweight = AsteroidFactory.getAsteroid(
                  sizes[type], sizes[type], sizes[type] * 10,
                  colors[type], textures[type], materials[type]
              );
  
              asteroids.add(new AsteroidContext(
                  flyweight,
                  100 + i * 50, // Simple x: 100, 150, 200, 250...
                  200 + i * 30, // Simple y: 200, 230, 260, 290...
                  1, // All move right with velocity 1
                  2  // All move down with velocity 2
              ));
          }
  
          System.out.println("Created " + asteroids.size() + " asteroid contexts");
          System.out.println("Total flyweight objects: " + AsteroidFactory.getFlyweightCount());
      }
  
      public void renderAll() {
          System.out.println("\n--- Rendering first 5 asteroids ---");
          for (int i = 0; i < Math.min(5, asteroids.size()); i++) {
              asteroids.get(i).render();
          }
      }
  
      public long calculateMemoryUsage() {
          long contextMemory = asteroids.size() * AsteroidContext.getMemoryUsage();
          long flyweightMemory = AsteroidFactory.getTotalFlyweightMemory();
          return contextMemory + flyweightMemory;
      }
  
      public int getAsteroidCount() {
          return asteroids.size();
      }
  }
  
  public class WithFlyWeight {
      public static void main(String[] args) {
          final int ASTEROID_COUNT = 1_000_000;
  
          System.out.println("\nTESTING WITH FLYWEIGHT PATTERN");
          SpaceGameWithFlyweight game = new SpaceGameWithFlyweight();
  
          game.spawnAsteroids(ASTEROID_COUNT);
  
          // Show first 5 asteroids to see the pattern
          game.renderAll();
  
          // Calculate and display memory usage
          long totalMemory = game.calculateMemoryUsage();
  
          System.out.println("\n=== MEMORY USAGE ===");
          System.out.println("Total asteroids: " + ASTEROID_COUNT);
          System.out.println("Memory per asteroid: " + AsteroidContext.getMemoryUsage() + " bytes");
          System.out.println("Total memory used: " + totalMemory + " bytes");
          System.out.println("Memory in MB: " + (totalMemory / (1024.0 * 1024.0)) + " MB");
      }
  }
  