【设计模式】七大设计原则
【设计模式】第一章:单例模式
【设计模式】第二章:工厂模式
【设计模式】第三章:建造者模式
【设计模式】第四章:原型模式
【设计模式】第五章:适配器模式
【设计模式】第六章:装饰器模式
【设计模式】第七章:代理模式
【设计模式】第八章:桥接模式
【设计模式】第九章:外观模式 / 门面模式
【设计模式】第十章:组合模式
【设计模式】第十一章:享元模式
【设计模式】第十二章:观察者模式
【设计模式】第十三章:模板方法模式
【设计模式】第十四章:策略模式
【设计模式】第十五章:责任链模式
【设计模式】第十六章:迭代器模式
【设计模式】第十七章:状态模式
【设计模式】第十八章:备忘录模式
【设计模式】第十九章:访问者模式
【设计模式】第二十章:解释器模式
【设计模式】第二十一章:命令模式
【设计模式】第二十二章:中介者模式
摘自百度百科:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式要求对象拥有一个可以克隆自己的方法,如此一来,当通过原型实例创建新对象时,就可以不用关心实例本身,也无需通过new对象来实现。
深克隆和浅克隆都是指对象复制的方式,但它们之间有一些区别。
深克隆创建一个新对象,并且将原始对象及其所有嵌套对象的数据复制到新对象中。这意味着,新对象的所有属性都是不同的对象实例。这样,如果你改变原始对象中的任何属性,新对象的对应属性不会受到影响,并且反之亦然。深克隆通常需要更多的时间和资源来复制所有属性和嵌套对象。
浅克隆只会复制原始对象中的所有属性,但是所有嵌套的对象都将是原始对象中相应属性的引用。这意味着,新对象的属性和原始对象中的属性将共享对象实例。因此,如果你在新对象中更改一个嵌套对象的属性,则原始对象中相应的属性也会受到影响,反之亦然。相对于深克隆,浅克隆需要的时间和资源更少,但可能会导致意外的行为,因为对象引用可能会被共享并且相互影响。
原型模式具体有两种实现方式,一种是简单形式,另一种是登记形式。我们就这两种形式来探讨一下原型模式的实现方式。
客户(Client)
提出创建对象的请求的角色
抽象原型(Prototype)
规定具体原型类要实现的方法
具体原型(Concrete Prototype)
真正实现创建对象的角色
public abstract class Prototype {
private String name;
public Prototype(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
/**
* 克隆方法
* @return Prototype
*/
public abstract Prototype clone();
}
public class ConcretePrototypeA extends Prototype {
public ConcretePrototypeA (String name) {
super(name);
}
public Prototype clone() {
return new ConcretePrototype(this.name);
}
}
public class ConcretePrototypeB extends Prototype {
public ConcretePrototypeB (String name) {
super(name);
}
public Prototype clone() {
return new ConcretePrototype(this.name);
}
}
public static void main() {
System.out.println("prototype1");
ConcretePrototype1 prototype1 = new ConcretePrototype1("prototype1");
Prototype clone1 = prototype1.clone();
System.out.println("prototype1:" + prototype1);
System.out.println("clone:" + clone1);
System.out.println("prototype2");
ConcretePrototype2 prototype2 = new ConcretePrototype2("prototype2");
Prototype clone2 = prototype2.clone();
System.out.println("prototype2:" + prototype2);
System.out.println("clone:" + clone2);
}
客户(Client)
提出创建对象的请求的角色
抽象原型角色(Prototype)
规定具体原型类要实现的方法
具体原型角色(Concrete Prototype)
真正实现创建对象的角色
原型管理器(Prototype Manager)
提供原型对象的创建以及其他管理的方法
抽象原型对象(Prototype)
public interface Prototype {
public Prototype clone();
public String getName();
public void setName(String name);
}
具体原型A(Concrete Prototype A)
public class ConcretePrototypeA implements Prototype {
private String name;
@Override
public String getName() {
return this.name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public Prototype clone() {
Prototype prototype = new ConcretePrototypeA();
prototype.setName(this.name);
return prototype;
}
@Override
public String toString() {
return "ConcretePrototypeA [name=" + name + "]";
}
}
public class ConcretePrototypeB implements Prototype {
private String name;
@Override
public String getName() {
return this.name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public Prototype clone() {
Prototype prototype = new ConcretePrototypeB();
prototype.setName(this.name);
return prototype;
}
@Override
public String toString() {
return "ConcretePrototypeB [name=" + name + "]";
}
}
public class PrototypeManager {
/**
* 记录原型的编号同原型实例的对象关系
*/
private static Map<String, Prototype> map = new HashMap<>();
/**
* 私有化构造方法,避免从外部创建实例
*/
private PrototypeManager(){};
/**
* 向原型管理器里面添加或者修改原型实例
*
* @param prototypeId 原型编号
* @param prototype 原型实例
*/
public static void setPrototype(String prototypeId, Prototype prototype) {
map.put(prototypeId, prototype);
}
/**
* 根据原型编号删除原型实例
*
* @param prototypeId 原型编号
*/
public static void removePrototype(String prototypeId) {
map.remove(prototypeId);
}
/**
* 根据原型编号获取原型实例
*
* @param prototypeId 原型编号
* @return 原型实例对象
* @throws RuntimeException
*/
public static Prototype getPrototype(String prototypeId) throws RuntimeException {
Prototype prototype = map.get(prototypeId);
if(Objects.isNull(prototype)){
throw new RuntimeException("原型" + prototypeId + "不存在");
}
return prototype;
}
}
public class Client {
public static void main(String[] args){
try {
// 创建实例
Prototype prototypeA = new ConcretePrototypeA();
// 注册实例
PrototypeManager.setPrototype("prototypeA",prototypeA);
// 克隆
Prototype prototypeC = PrototypeManager.getPrototype("prototypeA").clone();
prototypeC.setName("张三");
System.out.println("第一个实例副本:" + prototypeC);
// 创建实例
Prototype prototypeB = new ConcretePrototypeB();
// 注册实例
PrototypeManager.setPrototype("prototypeB",prototypeB);
// 克隆
Prototype prototypeD = PrototypeManager.getPrototype("prototypeB").clone();
prototypeD.setName("李四");
System.out.println("第二个实例副本:" + prototypeD);
// 销毁第一个实例
PrototypeManager.removePrototype("prototypeA");
// 再次克隆第一个实例
Prototype prototypeE = PrototypeManager.getPrototype("prototypeA").clone();
prototypeE.setName("王五");
System.out.println("第一个实例副本:" + prototypeE);
} catch (Exception e) {
e.printStackTrace();
}
}
}
以下部分内容摘自菜鸟教程
意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
主要解决:在运行期建立和删除原型。
何时使用: 1、当一个系统应该独立于它的产品创建,构成和表示时。 2、当要实例化的类是在运行时刻指定时,例如,通过动态装载。 3、为了避免创建一个与产品类层次平行的工厂类层次时。 4、当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
如何解决:利用已有的一个原型对象,快速地生成和原型对象一样的实例。
关键代码:
应用实例:
优点:
缺点:
使用场景:
需要注意的是,原型模式的使用场景应遵循以下几个条件:
总而言之,原型模式在需要高效创建对象副本、保护对象状态、动态配置对象等场景下是非常有用的。它提供了一种灵活的方式来创建和复制对象,避免了传统实例化的开销和复杂性。
关注博客和公众号获取最新文章
Bummon’s Blog | Bummon’s Home | 公众号