设计模式之:原型模式

什么是原型模式?

原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新对象,而不是通过新建类的方式。原型模式允许一个对象再创建另外一个可定制的对象,无需知道创建的细节。

核心思想

原型模式的核心思想是:通过复制(克隆)现有对象来创建新对象,而不是通过new关键字实例化。 这就像细胞的自我复制,基于一个模板快速生成新的个体。

生活中的原型模式

想象一下印章的使用:

  • 你有一个原始印章(原型)
  • 想要多个相同的图案,不需要重新雕刻
  • 只需要用印泥复制(克隆)即可
  • 每个复制品都和原始印章一样

印章就是原型,复制过程就是克隆!

模式结构

原型模式包含三个核心角色:

  1. 抽象原型(Prototype):声明克隆方法的接口
  2. 具体原型(Concrete Prototype):实现克隆方法的具体类
  3. 客户端(Client):通过克隆方法创建新对象

基础示例:图形复制系统

1. 抽象原型接口

/**
 * 图形接口 - 抽象原型
 * 声明克隆方法
 */
public interface Shape extends Cloneable {
    /**
     * 克隆方法
     */
    Shape clone();
    
    /**
     * 绘制图形
     */
    void draw();
    
    /**
     * 获取图形信息
     */
    String getInfo();
    
    /**
     * 设置颜色
     */
    void setColor(String color);
    
    /**
     * 获取颜色
     */
    String getColor();
}

2. 具体原型类

import java.util.ArrayList;
import java.util.List;

/**
 * 圆形 - 具体原型
 */
public class Circle implements Shape {
    private int radius;
    private String color;
    private List<String> tags;
    
    public Circle(int radius, String color) {
        this.radius = radius;
        this.color = color;
        this.tags = new ArrayList<>();
        System.out.println("🔄 创建新的圆形对象(构造函数调用)");
        // 模拟复杂的初始化过程
        simulateComplexInitialization();
    }
    
    @Override
    public Shape clone() {
        System.out.println("⚡ 通过克隆创建圆形副本");
        try {
            Circle clone = (Circle) super.clone();
            // 对引用类型进行深拷贝
            clone.tags = new ArrayList<>(this.tags);
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("克隆失败", e);
        }
    }
    
    @Override
    public void draw() {
        System.out.printf("🎯 绘制圆形: 半径=%d, 颜色=%s, 标签=%s%n", 
                         radius, color, tags);
    }
    
    @Override
    public String getInfo() {
        return String.format("圆形[半径=%d, 颜色=%s, 标签=%s]", radius, color, tags);
    }
    
    @Override
    public void setColor(String color) {
        this.color = color;
    }
    
    @Override
    public String getColor() {
        return color;
    }
    
    public void setRadius(int radius) {
        this.radius = radius;
    }
    
    public int getRadius() {
        return radius;
    }
    
    public void addTag(String tag) {
        this.tags.add(tag);
    }
    
    public List<String> getTags() {
        return new ArrayList<>(tags);
    }
    
    /**
     * 模拟复杂的初始化过程
     */
    private void simulateComplexInitialization() {
        try {
            Thread.sleep(100); // 模拟耗时操作
            // 模拟从配置文件或数据库加载数据
            tags.add("几何图形");
            tags.add("对称图形");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

/**
 * 矩形 - 具体原型
 */
public class Rectangle implements Shape {
    private int width;
    private int height;
    private String color;
    private List<Point> points;
    
    public Rectangle(int width, int height, String color) {
        this.width = width;
        this.height = height;
        this.color = color;
        this.points = new ArrayList<>();
        initializePoints();
        System.out.println("🔄 创建新的矩形对象(构造函数调用)");
        simulateComplexInitialization();
    }
    
    @Override
    public Shape clone() {
        System.out.println("⚡ 通过克隆创建矩形副本");
        try {
            Rectangle clone = (Rectangle) super.clone();
            // 深拷贝引用类型
            clone.points = new ArrayList<>();
            for (Point point : this.points) {
                clone.points.add(point.clone());
            }
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("克隆失败", e);
        }
    }
    
    @Override
    public void draw() {
        System.out.printf("📐 绘制矩形: 宽=%d, 高=%d, 颜色=%s%n", width, height, color);
    }
    
    @Override
    public String getInfo() {
        return String.format("矩形[宽=%d, 高=%d, 颜色=%s, 顶点数=%d]", 
                           width, height, color, points.size());
    }
    
    @Override
    public void setColor(String color) {
        this.color = color;
    }
    
    @Override
    public String getColor() {
        return color;
    }
    
    public void setWidth(int width) {
        this.width = width;
        initializePoints();
    }
    
    public void setHeight(int height) {
        this.height = height;
        initializePoints();
    }
    
    public int getWidth() {
        return width;
    }
    
    public int getHeight() {
        return height;
    }
    
    /**
     * 初始化顶点坐标
     */
    private void initializePoints() {
        points.clear();
        points.add(new Point(0, 0));
        points.add(new Point(width, 0));
        points.add(new Point(width, height));
        points.add(new Point(0, height));
    }
    
    /**
     * 模拟复杂的初始化过程
     */
    private void simulateComplexInitialization() {
        try {
            Thread.sleep(150); // 模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

/**
 * 点坐标类 - 支持克隆
 */
class Point implements Cloneable {
    private int x;
    private int y;
    
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    @Override
    public Point clone() {
        try {
            return (Point) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("点坐标克隆失败", e);
        }
    }
    
    @Override
    public String toString() {
        return String.format("(%d,%d)", x, y);
    }
}

3. 图形注册表(原型管理器)

import java.util.HashMap;
import java.util.Map;

/**
 * 图形注册表 - 原型管理器
 * 管理和提供各种原型对象
 */
public class ShapeRegistry {
    private static ShapeRegistry instance;
    private final Map<String, Shape> prototypes;
    
    private ShapeRegistry() {
        this.prototypes = new HashMap<>();
        initializePrototypes();
    }
    
    public static ShapeRegistry getInstance() {
        if (instance == null) {
            instance = new ShapeRegistry();
        }
        return instance;
    }
    
    /**
     * 初始化原型对象
     */
    private void initializePrototypes() {
        System.out.println("🎨 初始化图形原型库...");
        
        // 创建各种预定义的原型
        prototypes.put("red_circle", new Circle(10, "红色"));
        prototypes.put("blue_circle", new Circle(15, "蓝色"));
        prototypes.put("green_rectangle", new Rectangle(20, 10, "绿色"));
        prototypes.put("yellow_rectangle", new Rectangle(30, 20, "黄色"));
        
        // 为原型添加标签
        ((Circle) prototypes.get("red_circle")).addTag("标准圆形");
        ((Circle) prototypes.get("blue_circle")).addTag("大圆形");
        ((Rectangle) prototypes.get("green_rectangle")).addTag("小矩形");
        ((Rectangle) prototypes.get("yellow_rectangle")).addTag("大矩形");
        
        System.out.println("✅ 图形原型库初始化完成");
    }
    
    /**
     * 根据类型获取原型副本
     */
    public Shape getShape(String type) {
        Shape prototype = prototypes.get(type);
        if (prototype == null) {
            throw new IllegalArgumentException("未知的图形类型: " + type);
        }
        return prototype.clone();
    }
    
    /**
     * 注册新的原型
     */
    public void registerPrototype(String type, Shape prototype) {
        prototypes.put(type, prototype);
        System.out.println("📝 注册新原型: " + type);
    }
    
    /**
     * 显示所有可用的原型
     */
    public void displayAvailablePrototypes() {
        System.out.println("\n📚 可用的图形原型:");
        System.out.println("-".repeat(50));
        prototypes.forEach((key, shape) -> {
            System.out.printf("🔑 %-20s -> %s%n", key, shape.getInfo());
        });
    }
}

4. 客户端使用

/**
 * 图形编辑器客户端
 */
public class ShapeEditor {
    public static void main(String[] args) {
        System.out.println("=== 原型模式演示 - 图形编辑器 ===\n");
        
        // 获取图形注册表
        ShapeRegistry registry = ShapeRegistry.getInstance();
        
        // 显示可用原型
        registry.displayAvailablePrototypes();
        
        System.out.println("\n🎯 原型克隆演示:");
        System.out.println("-".repeat(50));
        
        // 演示1:基础克隆
        demonstrateBasicCloning(registry);
        
        // 演示2:性能对比
        demonstratePerformanceComparison();
        
        // 演示3:自定义修改
        demonstrateCustomization(registry);
        
        // 演示4:动态注册原型
        demonstrateDynamicRegistration(registry);
    }
    
    /**
     * 演示基础克隆
     */
    private static void demonstrateBasicCloning(ShapeRegistry registry) {
        System.out.println("1. 基础克隆演示:");
        
        // 从原型库获取图形副本
        Shape circle1 = registry.getShape("red_circle");
        Shape circle2 = registry.getShape("red_circle");
        Shape rectangle1 = registry.getShape("green_rectangle");
        
        System.out.println("\n📋 克隆结果:");
        System.out.println("圆形1: " + circle1.getInfo());
        System.out.println("圆形2: " + circle2.getInfo());
        System.out.println("矩形1: " + rectangle1.getInfo());
        
        // 验证是否是不同对象
        System.out.println("\n🔍 对象验证:");
        System.out.println("圆形1和圆形2是同一个对象吗? " + (circle1 == circle2));
        System.out.println("圆形1和圆形2内容相同吗? " + circle1.getInfo().equals(circle2.getInfo()));
    }
    
    /**
     * 演示性能对比
     */
    private static void demonstratePerformanceComparison() {
        System.out.println("\n2. 性能对比演示:");
        System.out.println("-".repeat(40));
        
        // 测试使用new创建对象
        long startTime = System.currentTimeMillis();
        testWithNewOperator();
        long newTime = System.currentTimeMillis() - startTime;
        
        // 测试使用克隆创建对象
        startTime = System.currentTimeMillis();
        testWithClone();
        long cloneTime = System.currentTimeMillis() - startTime;
        
        System.out.println("\n⏱️ 性能对比结果:");
        System.out.printf("使用new操作符: %d ms%n", newTime);
        System.out.printf("使用克隆方法: %d ms%n", cloneTime);
        System.out.printf("性能提升: %.1f%%%n", 
            (1 - (double) cloneTime / newTime) * 100);
    }
    
    private static void testWithNewOperator() {
        System.out.println("测试使用new创建100个圆形...");
        for (int i = 0; i < 100; i++) {
            new Circle(10, "红色"); // 每次都要执行复杂初始化
        }
    }
    
    private static void testWithClone() {
        System.out.println("测试使用克隆创建100个圆形...");
        Circle prototype = new Circle(10, "红色"); // 只初始化一次
        for (int i = 0; i < 100; i++) {
            prototype.clone(); // 快速克隆
        }
    }
    
    /**
     * 演示自定义修改
     */
    private static void demonstrateCustomization(ShapeRegistry registry) {
        System.out.println("\n3. 克隆后自定义演示:");
        System.out.println("-".repeat(40));
        
        // 获取原型副本
        Shape circle = registry.getShape("blue_circle");
        Shape rectangle = registry.getShape("yellow_rectangle");
        
        System.out.println("原始图形:");
        circle.draw();
        rectangle.draw();
        
        // 修改克隆后的对象
        circle.setColor("紫色");
        ((Circle) circle).setRadius(25);
        ((Circle) circle).addTag("自定义圆形");
        
        rectangle.setColor("橙色");
        ((Rectangle) rectangle).setWidth(40);
        ((Rectangle) rectangle).setHeight(30);
        
        System.out.println("\n修改后的图形:");
        circle.draw();
        rectangle.draw();
        
        // 验证原型未被修改
        Shape originalCircle = registry.getShape("blue_circle");
        System.out.println("\n🔍 验证原型完整性:");
        System.out.println("原型: " + originalCircle.getInfo());
        System.out.println("克隆: " + circle.getInfo());
        System.out.println("原型和克隆相同吗? " + originalCircle.getInfo().equals(circle.getInfo()));
    }
    
    /**
     * 演示动态注册原型
     */
    private static void demonstrateDynamicRegistration(ShapeRegistry registry) {
        System.out.println("\n4. 动态注册原型演示:");
        System.out.println("-".repeat(40));
        
        // 创建自定义图形并注册为原型
        Circle customCircle = new Circle(8, "粉色");
        customCircle.addTag("自定义");
        customCircle.addTag("特殊图形");
        
        registry.registerPrototype("pink_small_circle", customCircle);
        
        // 使用新注册的原型
        Shape clonedCircle1 = registry.getShape("pink_small_circle");
        Shape clonedCircle2 = registry.getShape("pink_small_circle");
        
        System.out.println("使用新原型创建的图形:");
        clonedCircle1.draw();
        clonedCircle2.draw();
        
        // 显示更新后的原型库
        registry.displayAvailablePrototypes();
    }
}

完整示例:游戏角色系统

让我们通过一个更复杂的游戏角色系统来深入理解原型模式。

1. 游戏角色原型

import java.util.*;

/**
 * 游戏角色接口 - 抽象原型
 */
public interface GameCharacter extends Cloneable {
    GameCharacter clone();
    void display();
    String getCharacterInfo();
    void setLevel(int level);
    void setHealth(int health);
}

/**
 * 战士角色 - 具体原型
 */
class Warrior implements GameCharacter {
    private String name;
    private int level;
    private int health;
    private List<String> skills;
    private Equipment equipment;
    private Map<String, Integer> attributes;
    
    public Warrior(String name) {
        this.name = name;
        this.level = 1;
        this.health = 100;
        this.skills = new ArrayList<>();
        this.equipment = new Equipment();
        this.attributes = new HashMap<>();
        initializeWarrior();
        System.out.println("⚔️ 创建新的战士角色: " + name);
        simulateComplexInitialization();
    }
    
    @Override
    public GameCharacter clone() {
        System.out.println("⚡ 克隆战士角色: " + name);
        try {
            Warrior clone = (Warrior) super.clone();
            // 深拷贝所有引用类型
            clone.skills = new ArrayList<>(this.skills);
            clone.equipment = this.equipment.clone();
            clone.attributes = new HashMap<>(this.attributes);
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("战士克隆失败", e);
        }
    }
    
    @Override
    public void display() {
        System.out.printf("🧔 战士 %s [等级%d, 生命值%d]%n", name, level, health);
        System.out.printf("   技能: %s%n", skills);
        System.out.printf("   装备: %s%n", equipment);
        System.out.printf("   属性: %s%n", attributes);
    }
    
    @Override
    public String getCharacterInfo() {
        return String.format("战士%s(等级%d,生命%d,技能%d个)", 
                           name, level, health, skills.size());
    }
    
    @Override
    public void setLevel(int level) {
        this.level = level;
    }
    
    @Override
    public void setHealth(int health) {
        this.health = health;
    }
    
    public void addSkill(String skill) {
        this.skills.add(skill);
    }
    
    public void setAttribute(String attribute, int value) {
        this.attributes.put(attribute, value);
    }
    
    public void equipWeapon(String weapon) {
        this.equipment.setWeapon(weapon);
    }
    
    public void equipArmor(String armor) {
        this.equipment.setArmor(armor);
    }
    
    /**
     * 初始化战士属性
     */
    private void initializeWarrior() {
        skills.add("重击");
        skills.add("防御");
        attributes.put("力量", 15);
        attributes.put("敏捷", 8);
        attributes.put("体力", 12);
        equipment.setWeapon("长剑");
        equipment.setArmor("锁子甲");
    }
    
    /**
     * 模拟复杂的初始化过程
     */
    private void simulateComplexInitialization() {
        try {
            Thread.sleep(200); // 模拟从数据库加载数据等操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

/**
 * 法师角色 - 具体原型
 */
class Mage implements GameCharacter {
    private String name;
    private int level;
    private int health;
    private List<String> spells;
    private Equipment equipment;
    private Map<String, Integer> attributes;
    private int mana;
    
    public Mage(String name) {
        this.name = name;
        this.level = 1;
        this.health = 80;
        this.mana = 100;
        this.spells = new ArrayList<>();
        this.equipment = new Equipment();
        this.attributes = new HashMap<>();
        initializeMage();
        System.out.println("🧙 创建新的法师角色: " + name);
        simulateComplexInitialization();
    }
    
    @Override
    public GameCharacter clone() {
        System.out.println("⚡ 克隆法师角色: " + name);
        try {
            Mage clone = (Mage) super.clone();
            // 深拷贝
            clone.spells = new ArrayList<>(this.spells);
            clone.equipment = this.equipment.clone();
            clone.attributes = new HashMap<>(this.attributes);
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("法师克隆失败", e);
        }
    }
    
    @Override
    public void display() {
        System.out.printf("🧙 法师 %s [等级%d, 生命值%d, 魔法值%d]%n", 
                         name, level, health, mana);
        System.out.printf("   法术: %s%n", spells);
        System.out.printf("   装备: %s%n", equipment);
        System.out.printf("   属性: %s%n", attributes);
    }
    
    @Override
    public String getCharacterInfo() {
        return String.format("法师%s(等级%d,生命%d,魔法%d,法术%d个)", 
                           name, level, health, mana, spells.size());
    }
    
    @Override
    public void setLevel(int level) {
        this.level = level;
    }
    
    @Override
    public void setHealth(int health) {
        this.health = health;
    }
    
    public void addSpell(String spell) {
        this.spells.add(spell);
    }
    
    public void setMana(int mana) {
        this.mana = mana;
    }
    
    /**
     * 初始化法师属性
     */
    private void initializeMage() {
        spells.add("火球术");
        spells.add("寒冰箭");
        attributes.put("智力", 18);
        attributes.put("精神", 12);
        attributes.put("体力", 6);
        equipment.setWeapon("法杖");
        equipment.setArmor("布甲");
    }
    
    private void simulateComplexInitialization() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

/**
 * 装备类 - 支持克隆
 */
class Equipment implements Cloneable {
    private String weapon;
    private String armor;
    private String accessory;
    
    public Equipment() {
        this.weapon = "无";
        this.armor = "无";
        this.accessory = "无";
    }
    
    @Override
    public Equipment clone() {
        try {
            return (Equipment) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("装备克隆失败", e);
        }
    }
    
    public void setWeapon(String weapon) {
        this.weapon = weapon;
    }
    
    public void setArmor(String armor) {
        this.armor = armor;
    }
    
    public void setAccessory(String accessory) {
        this.accessory = accessory;
    }
    
    @Override
    public String toString() {
        return String.format("武器:%s, 护甲:%s, 饰品:%s", weapon, armor, accessory);
    }
}

2. 角色管理器

import java.util.HashMap;
import java.util.Map;

/**
 * 角色管理器 - 原型管理器
 */
public class CharacterManager {
    private static CharacterManager instance;
    private final Map<String, GameCharacter> characterPrototypes;
    
    private CharacterManager() {
        this.characterPrototypes = new HashMap<>();
        initializePrototypes();
    }
    
    public static CharacterManager getInstance() {
        if (instance == null) {
            instance = new CharacterManager();
        }
        return instance;
    }
    
    /**
     * 初始化角色原型
     */
    private void initializePrototypes() {
        System.out.println("🎮 初始化角色原型库...");
        
        // 创建预定义的角色原型
        Warrior warrior = new Warrior("标准战士");
        warrior.setLevel(5);
        warrior.addSkill("旋风斩");
        characterPrototypes.put("standard_warrior", warrior);
        
        Mage mage = new Mage("标准法师");
        mage.setLevel(5);
        mage.addSpell("暴风雪");
        characterPrototypes.put("standard_mage", mage);
        
        // 创建高级角色原型
        Warrior eliteWarrior = new Warrior("精英战士");
        eliteWarrior.setLevel(10);
        eliteWarrior.setHealth(150);
        eliteWarrior.addSkill("雷霆一击");
        eliteWarrior.equipWeapon("巨斧");
        eliteWarrior.equipArmor("板甲");
        characterPrototypes.put("elite_warrior", eliteWarrior);
        
        Mage eliteMage = new Mage("精英法师");
        eliteMage.setLevel(10);
        eliteMage.setHealth(120);
        eliteMage.setMana(200);
        eliteMage.addSpell("陨石术");
        characterPrototypes.put("elite_mage", eliteMage);
        
        System.out.println("✅ 角色原型库初始化完成");
    }
    
    /**
     * 获取角色副本
     */
    public GameCharacter getCharacter(String type) {
        GameCharacter prototype = characterPrototypes.get(type);
        if (prototype == null) {
            throw new IllegalArgumentException("未知的角色类型: " + type);
        }
        return prototype.clone();
    }
    
    /**
     * 注册新原型
     */
    public void registerPrototype(String type, GameCharacter prototype) {
        characterPrototypes.put(type, prototype);
        System.out.println("📝 注册新角色原型: " + type);
    }
    
    /**
     * 显示所有可用原型
     */
    public void displayAvailablePrototypes() {
        System.out.println("\n📚 可用的角色原型:");
        System.out.println("-".repeat(50));
        characterPrototypes.forEach((key, character) -> {
            System.out.printf("🔑 %-20s -> %s%n", key, character.getCharacterInfo());
        });
    }
    
    /**
     * 创建自定义角色
     */
    public GameCharacter createCustomCharacter(String type, String name) {
        GameCharacter character = getCharacter(type);
        // 这里可以添加自定义逻辑,比如重命名等
        return character;
    }
}

3. 游戏客户端

/**
 * 游戏客户端
 */
public class GameClient {
    public static void main(String[] args) {
        System.out.println("=== 原型模式演示 - 游戏角色系统 ===\n");
        
        CharacterManager manager = CharacterManager.getInstance();
        
        // 显示可用原型
        manager.displayAvailablePrototypes();
        
        System.out.println("\n🎯 角色克隆演示:");
        System.out.println("-".repeat(50));
        
        // 创建玩家队伍
        System.out.println("👥 创建玩家队伍:");
        
        GameCharacter player1 = manager.getCharacter("standard_warrior");
        GameCharacter player2 = manager.getCharacter("standard_mage");
        GameCharacter player3 = manager.getCharacter("elite_warrior");
        GameCharacter player4 = manager.getCharacter("elite_mage");
        
        // 显示队伍成员
        player1.display();
        player2.display();
        player3.display();
        player4.display();
        
        System.out.println("\n🔄 创建副本并自定义:");
        System.out.println("-".repeat(40));
        
        // 创建副本并自定义
        GameCharacter customWarrior = manager.getCharacter("standard_warrior");
        customWarrior.setLevel(8);
        customWarrior.setHealth(130);
        ((Warrior) customWarrior).addSkill("英勇跳跃");
        ((Warrior) customWarrior).equipWeapon("传说之剑");
        
        GameCharacter customMage = manager.getCharacter("standard_mage");
        customMage.setLevel(7);
        customMage.setHealth(95);
        ((Mage) customMage).addSpell("时空扭曲");
        ((Mage) customMage).setMana(180);
        
        System.out.println("自定义后的角色:");
        customWarrior.display();
        customMage.display();
        
        System.out.println("\n🎪 大规模角色创建演示:");
        System.out.println("-".repeat(40));
        
        // 演示大规模创建NPC
        createNPCArmy(manager);
        
        System.out.println("\n⏱️ 性能优势演示:");
        demonstratePerformanceAdvantage();
    }
    
    /**
     * 创建NPC军队
     */
    private static void createNPCArmy(CharacterManager manager) {
        System.out.println("创建NPC军队(50个战士,30个法师)...");
        
        long startTime = System.currentTimeMillis();
        
        // 使用原型模式快速创建大量NPC
        for (int i = 1; i <= 50; i++) {
            GameCharacter soldier = manager.getCharacter("standard_warrior");
            // 可以在这里进行个性化设置
            if (i % 10 == 0) {
                soldier.setLevel(3); // 每10个有一个小队长
            }
        }
        
        for (int i = 1; i <= 30; i++) {
            GameCharacter mage = manager.getCharacter("standard_mage");
            if (i % 5 == 0) {
                mage.setLevel(4); // 每5个有一个高级法师
            }
        }
        
        long duration = System.currentTimeMillis() - startTime;
        System.out.printf("✅ 创建80个NPC完成,耗时: %d ms%n", duration);
    }
    
    /**
     * 演示性能优势
     */
    private static void demonstratePerformanceAdvantage() {
        System.out.println("性能对比:创建100个复杂角色");
        
        // 测试传统方式
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100; i++) {
            new Warrior("战士" + i); // 每次都要完整初始化
        }
        long traditionalTime = System.currentTimeMillis() - startTime;
        
        // 测试原型模式
        Warrior prototype = new Warrior("原型战士");
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 100; i++) {
            prototype.clone(); // 基于原型快速克隆
        }
        long prototypeTime = System.currentTimeMillis() - startTime;
        
        System.out.printf("传统方式: %d ms%n", traditionalTime);
        System.out.printf("原型模式: %d ms%n", prototypeTime);
        System.out.printf("性能提升: %.1f%%%n", 
            (1 - (double) prototypeTime / traditionalTime) * 100);
    }
}

深拷贝 vs 浅拷贝

/**
 * 深拷贝和浅拷贝演示
 */
public class CopyDemo {
    public static void main(String[] args) {
        System.out.println("=== 深拷贝 vs 浅拷贝演示 ===\n");
        
        // 创建原始对象
        OriginalObject original = new OriginalObject("原始数据");
        original.addItem("项目A");
        original.addItem("项目B");
        
        System.out.println("原始对象: " + original);
        
        // 浅拷贝
        OriginalObject shallowCopy = original.shallowCopy();
        shallowCopy.setName("浅拷贝数据");
        shallowCopy.addItem("项目C");
        
        System.out.println("\n浅拷贝后:");
        System.out.println("原始对象: " + original);
        System.out.println("浅拷贝: " + shallowCopy);
        
        // 深拷贝
        OriginalObject deepCopy = original.deepCopy();
        deepCopy.setName("深拷贝数据");
        deepCopy.addItem("项目D");
        
        System.out.println("\n深拷贝后:");
        System.out.println("原始对象: " + original);
        System.out.println("深拷贝: " + deepCopy);
    }
}

class OriginalObject implements Cloneable {
    private String name;
    private List<String> items;
    private Date createTime;
    
    public OriginalObject(String name) {
        this.name = name;
        this.items = new ArrayList<>();
        this.createTime = new Date();
    }
    
    // 浅拷贝
    public OriginalObject shallowCopy() {
        try {
            return (OriginalObject) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("浅拷贝失败", e);
        }
    }
    
    // 深拷贝
    public OriginalObject deepCopy() {
        try {
            OriginalObject copy = (OriginalObject) super.clone();
            // 对引用类型进行深拷贝
            copy.items = new ArrayList<>(this.items);
            copy.createTime = (Date) this.createTime.clone();
            return copy;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("深拷贝失败", e);
        }
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void addItem(String item) {
        this.items.add(item);
    }
    
    @Override
    public String toString() {
        return String.format("OriginalObject{name='%s', items=%s, createTime=%s}", 
                           name, items, createTime);
    }
}

原型模式的优点

1. 性能提升

// 避免重复执行昂贵的初始化操作
// 特别适合创建成本高的对象

2. 简化对象创建

// 客户端不需要知道具体创建细节
// 通过简单克隆即可获得新对象

3. 动态配置

// 可以在运行时动态添加或删除原型
// 灵活性高

原型模式的缺点

1. 深拷贝复杂性

// 需要正确实现深拷贝
// 对于复杂对象图,实现可能很复杂

2. 需要支持克隆

// 所有需要克隆的类都要实现Cloneable接口
// 可能需要重写clone方法

适用场景

  1. 对象创建成本较高时
  2. 需要避免使用与产品类层次平行的工厂类层次时
  3. 一个类的实例只能有几个不同状态组合时
  4. 需要动态加载类时

最佳实践

1. 正确实现深拷贝

@Override
public Object clone() {
    try {
        MyClass clone = (MyClass) super.clone();
        // 对每个引用类型进行深拷贝
        clone.listField = new ArrayList<>(this.listField);
        clone.mapField = new HashMap<>(this.mapField);
        return clone;
    } catch (CloneNotSupportedException e) {
        throw new RuntimeException("克隆失败", e);
    }
}

2. 考虑使用拷贝构造函数

public MyClass(MyClass other) {
    this.field1 = other.field1;
    this.listField = new ArrayList<>(other.listField);
    // ...
}

3. 使用原型管理器

// 集中管理原型对象
// 提供统一的访问接口

总结

原型模式就像是对象的"复印机",可以快速创建对象的副本,避免重复的初始化工作。

核心价值:

  • 提高对象创建性能
  • 简化复杂对象的创建过程
  • 提供动态的对象创建机制

使用场景:

  • 对象创建成本高时
  • 需要创建大量相似对象时
  • 需要避免繁琐的初始化过程时

简单记忆:

对象创建太麻烦?原型模式来帮忙!
就像复印机一样,一键复制真便当。

掌握原型模式,能够让你在面对复杂对象创建时游刃有余,显著提升系统性能!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值