Java 中的原型模式:掌握对象克隆以实现高效实例化
约 3 分钟
也称为
- 克隆
原型设计模式的意图
原型模式用于指定要创建的对象类型,使用原型实例,并通过对象克隆来创建新的实例。
原型模式的详细解释,包括实际应用案例
现实世界中的例子
想象一家制造定制家具的公司。他们不会每次接到订单都从头开始制作家具,而是保留了他们最受欢迎设计的原型。当客户订购特定设计时,公司只需克隆该设计的原型并进行必要的定制。这种方法节省了时间和资源,因为基本结构和设计细节已经到位,使公司能够快速满足订单,同时保持一致的质量。
在这个场景中,家具原型就像软件中的对象原型,能够根据现有模型高效地创建新的定制家具。
简单来说
通过克隆现有的对象来创建一个新的对象。
维基百科说
原型模式是软件开发中的一种创建型设计模式。它用于在创建对象的类型由原型实例确定时使用,该原型实例被克隆以生成新的对象。
Java 中原型模式的编程示例
在 Java 中,建议如下实现原型模式。首先,创建一个带有克隆对象方法的接口。在本例中,Prototype
接口通过其 copy
方法实现了这一点。
public abstract class Prototype<T> implements Cloneable {
@SneakyThrows
public T copy() {
return (T) super.clone();
}
}
我们的示例包含不同生物的层次结构。例如,让我们看一下 Beast
和 OrcBeast
类。
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public abstract class Beast extends Prototype<Beast> {
public Beast(Beast source) {}
}
@EqualsAndHashCode(callSuper = false)
@RequiredArgsConstructor
public class OrcBeast extends Beast {
private final String weapon;
public OrcBeast(OrcBeast orcBeast) {
super(orcBeast);
this.weapon = orcBeast.weapon;
}
@Override
public String toString() {
return "Orcish wolf attacks with " + weapon;
}
}
我们不想深入太多细节,但完整的示例还包含基类 Mage
和 Warlord
,以及针对精灵和兽人的专门实现。
为了充分利用原型模式,我们创建了 HeroFactory
和 HeroFactoryImpl
类,以便从原型中生成不同类型的生物。
public interface HeroFactory {
Mage createMage();
Warlord createWarlord();
Beast createBeast();
}
@RequiredArgsConstructor
public class HeroFactoryImpl implements HeroFactory {
private final Mage mage;
private final Warlord warlord;
private final Beast beast;
public Mage createMage() {
return mage.copy();
}
public Warlord createWarlord() {
return warlord.copy();
}
public Beast createBeast() {
return beast.copy();
}
}
现在,我们可以通过克隆现有实例来展示原型模式的实际应用,生成新的生物。
public static void main(String[] args) {
var factory = new HeroFactoryImpl(
new ElfMage("cooking"),
new ElfWarlord("cleaning"),
new ElfBeast("protecting")
);
var mage = factory.createMage();
var warlord = factory.createWarlord();
var beast = factory.createBeast();
LOGGER.info(mage.toString());
LOGGER.info(warlord.toString());
LOGGER.info(beast.toString());
factory = new HeroFactoryImpl(
new OrcMage("axe"),
new OrcWarlord("sword"),
new OrcBeast("laser")
);
mage = factory.createMage();
warlord = factory.createWarlord();
beast = factory.createBeast();
LOGGER.info(mage.toString());
LOGGER.info(warlord.toString());
LOGGER.info(beast.toString());
}
以下是运行示例后的控制台输出。
08:36:19.012 [main] INFO com.iluwatar.prototype.App -- Elven mage helps in cooking
08:36:19.013 [main] INFO com.iluwatar.prototype.App -- Elven warlord helps in cleaning
08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Elven eagle helps in protecting
08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Orcish mage attacks with axe
08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Orcish warlord attacks with sword
08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Orcish wolf attacks with laser
原型模式的详细解释,包括实际应用案例
何时在 Java 中使用原型模式
- 当要实例化的类在运行时指定时,例如,通过动态加载。
- 为了避免构建与产品类层次结构平行的工厂类层次结构。
- 当类的实例只能具有一些不同的状态组合时。安装相应的原型并克隆它们可能比每次手动实例化类并使用适当的状态更方便。
- 当对象创建比克隆更昂贵时。
- 当要实例化的具体类在运行时未知时。
原型模式在 Java 中的实际应用
- 在 Java 中,
Object.clone()
方法是原型模式的经典实现。 - GUI 库通常使用原型来创建按钮、窗口和其他小部件。
- 在游戏开发中,创建具有相似属性的多个对象(如敌方角色)。
原型模式的优缺点
优点
在 Java 应用程序中利用原型模式
- 隐藏了实例化新对象的复杂性。
- 减少了类的数量。
- 允许在运行时添加和删除对象。
权衡
- 需要实现克隆机制,这可能很复杂。
- 深度克隆可能难以正确实现,尤其是当类具有带有循环引用的复杂对象图时。
相关的 Java 设计模式
- 抽象工厂:两者都涉及创建对象,但原型使用原型实例的克隆,而抽象工厂使用工厂方法创建对象。
- 单例:如果单例允许克隆其单个实例,则单例可以使用原型来创建实例。
- 组合:原型通常用于组合中,以允许动态创建组件树。