模式价值说明举例 坦克大战实现原型模式 使用java

本文通过坦克大战游戏实例,详细解析了原型模式的应用。介绍了如何通过改变参数而非创建子类的方式生成不同类型坦克,以此减少类的数量并保持接口的稳定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概要

2.内容

目录《一个实例讲完23种设计模式》

当前:原型模式(使用价值方面说明)

需求:坦克大战

创建两种坦克

坦克类型射程速度
b7070米时/70公里
b5050米时/70公里

类图

需求设计

我们假设坦克有两种,

一种数速度型坦克

一种是构造型坦克

速度型坦克的改变,无非就是改变数据,70,50,60

而发射行坦克无非改变的就是设计的距离 50 100 105

该实例通过,通过改变参数创建不同类型的坦克。

而不是通过类,如果分类的对象过多了,可以考虑通过该方式来消减类。

这里面其实用了桥接的思想。

这里改变的规格就相当于桥接对象。

类本身承担一个维度的变化,而这个规格的改变又承担了一个规格的变化。

坦克类型决定了坦克的基本功能,而规格的变化决定了他的性能。

模式价值:就是把类型迁移到参数里。

本来是需要分类的,但是用一个成员变量承载了这个变化,通过给一类对象设计不同的参数产生实际类别的对象。

优点:避免类型数量的增加。

适用情况:一个类对外接口稳定,但是在实际应用中,需要衍生很多多的子类。

子类的数量多到我们不愿意去接受,比如20个50个等等。

这时候我们怎么办,我们要降低类的数量。

什么降低呢,当然从问题入手。

看什么因素导致了这么多的类,这个因素一定是一个或几个成员变量。

那么我们把这些成员拿出来,给这些成员提供接口。

用设置这些成员的方法来来转换类的衍生数量。

这就是原型模式的基本创建过程。

这里有一个问题需要解释一下,什么叫稳定的接口呢。

举个例子吧

A{

int mA;

B mB;

public:

fun(int a)

fun2(int b)

private fun3();

}

mA的名称变化了,接口是否稳定。当然稳定。

mB的fun3变化了,接口是否稳定。当然稳定,因为外部接口没有变化。

fun的名称变化了,接口不稳定了。

fun2 的参数编程两个了,接口不稳定了。

这样,应该明白什么叫接口稳定了吧。

说白了,就是对外提供的函数没有变化。

接口没变,但是实际上对象变化了,变化有谁承载呢,由成员变量的变化承载;

当然也有可能是由函数内的不同处理逻辑承载,但是这个模式主要体现的是由变量承载的变化。

总结一下:用自己拷贝对象,用参数的变化承载对象的差异。

代码

interface ITank{
	void setmName(String mName);
	ITank clones();
	void exe();
	void setmSpecification(int mSpecification);
}
abstract class Tank implements ITank{
	int mSpecification;
	String mName;
	String mType;
	protected void setmType(String mType) {
		this.mType = mType;
	}
	public void setmName(String mName) {
		this.mName = mName;
	}
	public void setmSpecification(int mSpecification) {
		this.mSpecification = mSpecification;
	}
}
class ShotTank extends Tank{
	public ShotTank() {
		mType = "射击";
	}
	public ITank clones() {
		Tank t = new ShotTank();
		t.setmType(mType);
		return t;
	}
	public void exe() {
		System.out.println("型坦克型号:"+mType+mName);
		System.out.println("射击距离:"+mSpecification+"米");
	}
}
class RunTank extends Tank{
	public RunTank() {
		mType = "奔跑";
	}
	public ITank clones() {
		Tank t = new ShotTank();
		t.setmType(mType);
		return t;
	}
	public void exe() {
		System.out.println("坦克型号:"+mType+mName);
		System.out.println("速度:"+mSpecification+"公里");
	}
}
class ShotFactory{
	public ITank createS70(ITank shotPrototype) {
		ITank shot = shotPrototype.clones();
		shot.setmName("S70");
		shot.setmSpecification(70);
		return shot;
	}
	public ITank createS50(ITank shotPrototype) {
		ITank shot = shotPrototype.clones();
		shot.setmName("S51");
		shot.setmSpecification(50);
		return shot;
	}
	public ITank createS43(ITank shotPrototype) {
		ITank shot = shotPrototype.clones();
		shot.setmName("S43");
		shot.setmSpecification(40);
		return shot;
	}
}
class RunFactory{
	public ITank createR80(ITank runPrototype) {
		ITank run = runPrototype.clones();
		run.setmName("R80");
		run.setmSpecification(70);
		return run;
	}
	public ITank createR999(ITank runPrototype) {
		ITank run = runPrototype.clones();
		run.setmName("R999");
		run.setmSpecification(999);
		return run;
	}
	public ITank createR47(ITank runPrototype) {
		ITank run = runPrototype.clones();
		run.setmName("R47");
		run.setmSpecification(440);
		return run;
	}
}

public class Client {
	public static void main(String[] args) {
		System.out.println("Prototype 演示\n");
		ITank shotPrototype = new ShotTank();
		ITank runPrototype = new RunTank();
		
		ShotFactory sf = new ShotFactory();
		sf.createS43(shotPrototype).exe();
		sf.createS70(shotPrototype).exe();
		sf.createS50(shotPrototype).exe();
		
		System.out.println("");
		RunFactory rf = new RunFactory();
		rf.createR80(runPrototype).exe();
		rf.createR999(runPrototype).exe();
		rf.createR47(runPrototype).exe();
	}
}

 运行结果

3.关联知识 

1.原型模式

原型模式(Prototype Pattern)是创建型设计模式之一,通过复制现有对象来生成新对象,而非通过新建类实例。其核心思想是避免重复初始化对象,尤其适用于对象创建成本较高或需要动态配置的场景。


核心思想

  1. 克隆代替新建:通过实现克隆方法(如 clone())直接复制对象,跳过复杂的构造函数。
  2. 深拷贝 vs 浅拷贝
    • 浅拷贝:仅复制对象本身,引用类型字段共享(修改会影响原对象)。
    • 深拷贝:完全复制对象及其所有引用字段,新旧对象完全独立。

适用场景

  1. 对象创建复杂(如需要初始化大量数据或资源)。
  2. 需要动态配置对象类型(如通过类名动态加载类)。
  3. 避免重复初始化开销(如频繁创建相似对象)。

结构组成

  1. 原型接口(Prototype):声明克隆方法(如 clone())。
  2. 具体原型类(ConcretePrototype):实现克隆方法,处理深拷贝逻辑。
  3. 客户端(Client):通过调用 clone() 创建新对象。

代码示例(Java)

// 1. 定义原型接口
interface Prototype {
    Prototype clone();
}

// 2. 实现具体原型类(深拷贝示例)
class ConcretePrototype implements Prototype, Serializable {
    private String name;
    private List<String> hobbies;

    public ConcretePrototype(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = new ArrayList<>(hobbies); // 深拷贝引用字段
    }

    @Override
    public Prototype clone() {
        try {
            // 通过序列化实现深拷贝
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (Prototype) ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException("Clone failed", e);
        }
    }

    // Getters and Setters...
}

// 3. 客户端使用
public class Client {
    public static void main(String[] args) {
        List<String> hobbies = new ArrayList<>();
        hobbies.add("Reading");
        ConcretePrototype original = new ConcretePrototype("Alice", hobbies);
        
        ConcretePrototype cloned = (ConcretePrototype) original.clone();
        cloned.setName("Bob");
        cloned.getHobbies().add("Gaming");

        System.out.println(original.getName()); // Alice
        System.out.println(original.getHobbies()); // [Reading](未受影响)
    }
}

优缺点

优点缺点
避免重复初始化,性能高深拷贝实现复杂(需处理循环引用等)
动态配置对象类型(如反射)某些语言(如Java)需显式实现克隆方法
简化对象创建逻辑浅拷贝可能导致意外数据共享

注意事项

  1. 深拷贝实现:Java中默认 Object.clone() 是浅拷贝,需手动处理深拷贝(如序列化、递归复制)。
  2. 循环引用:深拷贝时需检测循环引用,避免无限递归。
  3. 性能权衡:深拷贝可能带来额外开销,需根据场景选择。

典型应用

  • 配置对象:复制默认配置后修改部分参数。
  • 复杂对象树:快速复制整个对象结构(如文档编辑器中的节点)。
  • 插件系统:动态加载类并复制实例。

通过合理使用原型模式,可以显著提升对象创建效率,尤其在需要频繁复制对象的场景中。

2.设计模式的原型模式深入分析 

设计模式之原型模式:深入分析

原型模式(Prototype Pattern)的核心是通过复制现有对象来创建新对象,而非通过构造函数或工厂方法。以下从实现细节、应用场景、优化策略、挑战与解决方案等角度展开深入分析。

一、实现细节与关键机制
  1. 浅拷贝 vs 深拷贝
    • 浅拷贝:仅复制对象的基本字段,引用类型字段共享(新旧对象指向同一内存地址)。
    • 深拷贝:完全复制对象及其所有引用字段,确保新旧对象完全独立。
    • 实现方式
      • Java:默认 Object.clone() 是浅拷贝,需重写并实现深拷贝逻辑。
      • 序列化:通过 ObjectOutputStream 和 ObjectInputStream 实现深拷贝(需处理 Serializable 接口)。
      • 手动复制:递归复制所有引用字段(需处理循环引用问题)。
  2. 循环引用问题
    • 场景:对象A引用对象B,对象B又引用对象A。
    • 解决方案
      • 哈希表标记:在序列化或手动复制时,用哈希表记录已复制的对象,避免重复复制。
      • 忽略循环引用:根据业务场景决定是否允许循环引用,或抛出异常。
二、应用场景扩展
  1. 高性能对象创建
    • 场景:对象初始化成本高(如数据库连接池、复杂计算对象)。
    • 优势:通过克隆跳过初始化过程,直接复制已准备好的状态。
  2. 动态配置与插件系统
    • 场景:根据运行时参数动态创建对象(如通过类名字符串加载类)。
    • 实现:结合反射机制,从原型对象派生新实例并动态配置。
  3. 对象状态备份与恢复
    • 场景:需要保存对象状态快照(如游戏存档、撤销操作)。
    • 实现:通过深拷贝创建状态副本,供后续恢复使用。
三、优化策略与设计扩展
  1. 原型管理器(Prototype Manager)
    • 作用:集中管理原型对象,提供注册、检索和克隆功能。
    • 优势
      • 缓存原型:避免重复创建原型对象。
      • 动态扩展:运行时注册新原型类型。
    • 示例代码

      class PrototypeManager {
          private Map<String, Prototype> prototypes = new HashMap<>();
      
          public void registerPrototype(String name, Prototype prototype) {
              prototypes.put(name, prototype);
          }
      
          public Prototype getPrototype(String name) {
              return prototypes.get(name).clone();
          }
      }
  2. 结合享元模式(Flyweight Pattern)
    • 场景:需要共享部分对象状态以减少内存占用。
    • 实现:将公共状态存储在原型对象中,克隆时仅复制可变状态。
  3. 线程安全设计
    • 问题:多线程环境下克隆可能导致数据不一致。
    • 解决方案
      • 同步克隆方法:使用 synchronized 关键字。
      • 不可变对象:确保原型对象在克隆过程中状态不变。
四、挑战与解决方案
  1. 深拷贝的复杂性
    • 挑战:对象结构复杂时,手动实现深拷贝容易出错。
    • 解决方案
      • 代码生成工具:如 Lombok 的 @DeepCopy 注解(需配合库支持)。
      • 反射+递归:自动遍历字段并复制(需处理私有字段和循环引用)。
  2. 维护成本
    • 挑战:对象结构变化时需同步修改克隆方法。
    • 解决方案
      • 统一克隆接口:强制子类实现克隆逻辑。
      • 自动化测试:验证克隆后的对象与原对象独立性。
  3. 性能权衡
    • 挑战:深拷贝可能带来额外性能开销。
    • 解决方案
      • 懒拷贝(Lazy Copy):仅在需要时复制引用字段。
      • 选择性拷贝:根据业务场景仅复制关键字段。
五、实际案例与框架应用
  1. 游戏开发
    • 场景:快速生成敌人、道具等对象。
    • 实现:定义基础原型(如 EnemyPrototype),通过克隆调整属性(如位置、血量)。
  2. 文档编辑器
    • 场景:复制节点及其子节点树。
    • 实现:深拷贝节点对象,保持父子关系引用。
  3. Spring框架中的原型作用域(Prototype Scope)
    • 机制:每次获取Bean时创建新实例(类似原型模式思想)。
    • 区别:Spring通过代理和依赖注入管理对象生命周期,而非手动克隆。
六、与其他创建型模式对比

模式核心思想适用场景
工厂模式通过子类决定创建对象对象类型明确,需解耦创建逻辑
抽象工厂创建一系列相关产品多产品族,需保证产品兼容性
建造者模式分步构建复杂对象对象构造过程复杂,需灵活配置
原型模式通过复制现有对象创建新对象对象创建成本高,需动态配置
七、最佳实践总结
  1. 明确拷贝需求:优先使用浅拷贝,仅在必要时实现深拷贝。
  2. 封装克隆逻辑:将克隆方法定义在接口中,强制子类实现。
  3. 结合管理器:通过原型管理器集中控制原型对象的注册和克隆。
  4. 权衡性能:在深拷贝开销较大时,考虑懒拷贝或选择性拷贝。
  5. 防御性编程:处理循环引用、空指针等边界情况。

通过深入理解原型模式的实现细节、应用场景和优化策略,可以更灵活地将其应用于实际开发中,提升代码的可维护性和性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值