一文带你了解Java设计模式之原型模式
定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式其实就是从一个对象在创建另外一个可定制的对象,不需要知道任何创建的细节
解决的问题
在运行期建立和删除原型。
经常用于:
类初始化消耗资源较多
构造函数比较复杂
核心要点
1.实现cloneable 接口,重写Object的clone方法
2.利用已有的一个原型对象,快速地生成和原型对象一样的实例。
类图
浅复制与深复制的区别
浅复制:基本数据类型进行值传递、引用数据类型的指针仍是指向原来的对象(成员变量)。
深复制:基本数据类型进行值传递、引用数据类型开辟新的内存空间。
代码实现
需求:实现克隆羊
有一头羊,需要经过赋值再克隆出两头。
未使用设计模式
public class Sheep {
private String name;
private Integer age;
private String color;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Sheep() {
}
public Sheep(String name, Integer age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
}
Main方法
public class Client {
public static void main(String[] args) {
//小羊
Sheep sheep=new Sheep("小红",8,"红色");
//克隆羊
Sheep sheep2=sheep;
Sheep sheep3=sheep;
System.out.println("通过赋值,指针还是指向sheep");
System.out.println(sheep);
System.out.println(sheep2);
System.out.println(sheep3);
}
}
//通过赋值,指针还是指向sheep
//com.promsing.creational.prototype.type1.Sheep@1b6d3586
//com.promsing.creational.prototype.type1.Sheep@1b6d3586
//com.promsing.creational.prototype.type1.Sheep@1b6d3586
实现Cloneable接口
Cloneable是标记型的接口,它们内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆,能使用Object.clone()方法。
如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。
实现Cloneable默认是浅复制
public class Sheep implements Cloneable {
private String name;
private Integer age;
private String color;
private Sheep friend;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Sheep() {
}
public Sheep getFriend() {
return friend;
}
public void setFriend(Sheep friend) {
this.friend = friend;
}
public Sheep(String name, Integer age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
@Override
protected Sheep clone() {
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
return sheep;
}
}
Main方法
public class ShallowClient {
public static void main(String[] args) {
Sheep sheep=new Sheep("小红",9,"红色");
sheep.setFriend(new Sheep("小黑",10,"黑色"));
Sheep sheep1 = sheep.clone();//开辟了新的空间
Sheep sheep2 = sheep.clone();
//浅复制
System.out.println("原型羊"+sheep);
System.out.println("克隆羊"+sheep1+"-朋友羊-"+sheep1.getFriend());
System.out.println("克隆羊"+sheep2+"-朋友羊-"+sheep2.getFriend());
//原型羊com.promsing.creational.prototype.type3.Sheep@1b6d3586
//克隆羊com.promsing.creational.prototype.type3.Sheep@4554617c-朋友羊-com.promsing.creational.prototype.type3.Sheep@74a14482
//克隆羊com.promsing.creational.prototype.type3.Sheep@1540e19d-朋友羊-com.promsing.creational.prototype.type3.Sheep@74a14482
}
}
一定要实现接口cloneable 否则报错:
Exception in thread "main" java.lang.CloneNotSupportedException: com.promsing.creational.prototype.type4.Sheep
at java.lang.Object.clone(Native Method)
at com.promsing.creational.prototype.type4.Sheep.clone(Sheep.java:76)
at com.promsing.creational.prototype.type4.DeepClient.main(DeepClient.java:14)
深复制-重写clone
羊类、房子类都需要实现Cloneable接口
房子类
public class House implements Cloneable {
//地址
private String address;
//尺寸
private Integer size;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
羊类
public class Sheep implements Cloneable {
private String name;
private Integer age;
private String color;
private House house;
public House getHouse() {
return house;
}
public void setHouse(House house) {
this.house = house;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Sheep() {
}
public Sheep(String name, Integer age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
@Override
protected Object clone() throws CloneNotSupportedException {
//对基本数据类型进行处理
Sheep deep = null;
deep = (Sheep) super.clone();
//对引用类型进行处理
//进行再次克隆
House clone = (House) deep.getHouse().clone();
deep.setHouse(clone);
return deep;
}
}
Main
public class DeepClient {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep=new Sheep("黑",90,"heisee");
sheep.setHouse(new House());
Sheep clone = (Sheep)sheep.clone();
System.out.println("原本的对象");
System.out.println(sheep);
System.out.println(sheep.getHouse());
System.out.println("克隆的对象");
System.out.println(clone);
System.out.println(clone.getHouse());
//开辟了新的内存空间
//原本的对象
//com.promsing.creational.prototype.type4.Sheep@1b6d3586
//com.promsing.creational.prototype.type4.House@4554617c
//克隆的对象
//com.promsing.creational.prototype.type4.Sheep@74a14482
//com.promsing.creational.prototype.type4.House@1540e19d
}
}
深复制-通过对象序列化实现(推荐)
羊类、房子类都需要实现Serializable接口。注意这里可以不实现Cloneable了。
房子类
public class House implements Serializable{
//地址
private String address;
//尺寸
private Integer size;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
}
羊类
public class Sheep implements Serializable {
private String name;
private Integer age;
private String color;
private House house;
public House getHouse() {
return house;
}
public void setHouse(House house) {
this.house = house;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Sheep() {
}
public Sheep(String name, Integer age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public Object deepClone() {
//创建流对象
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this); //当前这个对象以对象流的方式输出
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
Sheep copyObj = (Sheep) ois.readObject();
return copyObj;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return null;
} finally {
//关闭流
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (Exception e2) {
// TODO: handle exception
System.out.println(e2.getMessage());
}
}
}
}
Main
public class DeepClient {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep=new Sheep("黑",90,"heisee");
sheep.setHouse(new House());
Sheep clone = (Sheep)sheep.deepClone();
System.out.println("原本的对象");
System.out.println(sheep);
System.out.println(sheep.getHouse());
System.out.println("克隆的对象");
System.out.println(clone);
System.out.println(clone.getHouse());
}
}
拓展
Spring使用原型模式:@scope(“prototype”)
public static void main(String[] args) throws IOException {
//new一个容器
AnnotationConfigWebApplicationContext context =
new AnnotationConfigWebApplicationContext();
System.out.println("run success");
OrderService bean = context.getBean(OrderService.class);
}
//根据getBean点进去
public <T> T getBean(Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
}
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
后续走到了。AbstractBeanFactory类中的doGetBean方法中里边代码做判断mbd.isPrototype()
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//代码省略~~~~
}
else {
//代码省略~~~~
try {
//代码省略~~~~
// Create bean instance.
//判断是否是单例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//判断是否是多例(原型)
//这里会创建一个新的对象
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
//代码省略~~~~
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
//代码省略~~~~
}
return (T) bean;
}
ArrayList实现了Cloneable接口
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
到此这篇关于一文带你了解Java设计模式之原型模式的文章就介绍到这了,更多相关Java原型模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341