经过很多大神的总结,目前Java中一共23种经典的设计模式!
按照目的,设计模式可以分为以下三种用途:
1.创建型模式:用来处理对象的创建过程
2.结构型模式: 用来处理类或者对象的组合3.行为型模式:用来对类或对象怎样交互和怎样分配职责进行描述
工厂方法模式(Factory Method Pattern)
抽象工厂模式(Abstract Factory Pattern)
建造者模式(Builder Pattern)
原型模式(Prototype Pattern)
单例模式(Singleton Pattern)
适配器模式(Adapter Pattern)
桥接模式(Bridge Pattern)
组合模式(Composite Pattern)
装饰者模式(Decorator Pattern)
外观模式(Facade Pattern)
享元模式(Flyweight Pattern)
代理模式(Proxy Pattern)
责任链模式(Chain of Responsibility Pattern)
命令模式(Command Pattern)
解释器模式(Interpreter Pattern)
迭代器模式(Iterator Pattern)
中介者模式(Mediator Pattern)
备忘录模式(Memento Pattern)
观察者模式(Observer Pattern)
状态模式(State Pattern)
策略模式(Strategy Pattern)
模板方法模式(Template Method Pattern)
访问者模式(Visitor Pattern)
本篇文章主要为讲解一下原型模式!
一、原型模式的定义:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式(Prototype)是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,无需知道任何如何创建的细节。
工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。说白了就是对象的克隆。
二、原型模式(Prototype)解决了什么问题:
原型模式(Prototype)主要面对的问题是:“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。
三、原型模式(Prototype)如何使用:
下面是关于原型模式的一个简单的类图:
1.实现Cloneable接口。
它的作用只有一个:就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
2.重写Object类中的clone方法。(注意:clone()方法是Object类的,不是Cloneable的)
Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域是protected类型的,一般的类无法调用,因此,原型类Prototype需要将clone方法的作用域修改为public类型。
注: 实现一个接口,重写一个方法即完成了原型模式。在实际开发中,原型模式(Prototype)很少单独使用。经常与其他的设计模式混合使用,原型模式的原型类Prototype也常用抽象类来替代非抽象类也可以)。
实例1:用抽象类实现Cloneable接口
public abstract class AbstractSpoon implements Cloneable {
String spoonName;
public void setSpoonName(String spoonName) {
this.spoonName = spoonName;
}
public String getSpoonName() {
return this.spoonName;
}
public Object clone(){
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println("AbstractSpoon is not Cloneable");
}
return object;
}
}
抽象类的实现类:
public class SoupSpoon extends AbstractSpoon{
public SoupSpoon(){
setSpoonName("Soup Spoon");
}
}
实例2:用类实现Cloneable接口
public class Prototype implements Cloneable {
public Prototype clone() {
Prototype prototype = null;
try {
prototype = (Prototype)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return prototype;
}
}
public class ConcretePrototype extends Prototype {
public void show() {
System.out.println("原型模式实现类");
}
}
public class Client {
public static void main(String[] args) {
ConcretePrototype cp = new ConcretePrototype();
for(int i=0; i< 3; i++) {
ConcretePrototype clonecp = (ConcretePrototype)cp.clone();
clonecp.show();
}
}
}
四、原型模式的优点及适用场景
1.优点:使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
2.适用场景: 因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。
五、原型模式的注意事项
1.使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
2.深拷贝与浅拷贝。Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。
public class Prototype implements Cloneable {
private ArrayList list = new ArrayList();
public Prototype clone(){
Prototype prototype = null;
try {
prototype = (Prototype)super.clone();//只能做到浅拷贝
prototype.list = (ArrayList) this.list.clone();//为了实现深拷贝,在这里需要另行拷贝
} catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return prototype;
}
}
由于java提供的大部分容器类都实现了Cloneable接口,所以实现深拷贝并不是特别困难
六、详细讲解深拷贝与浅拷贝
浅拷贝:拷贝引用,就是实际上都指向同一个目标;简单的复制了对象的引用,实质上还是指向同一个对象,基本数据类型和string类的拷贝都是深拷贝
深拷贝:目标变成两个了,对象引用和对象一起给复制了一遍,实现了这个物理上的完全隔离。
拷贝有两种方式: 直接将源对象中的name的引用值拷贝给新对象的name字段, 或者是根据原Person对象中的name指向的字符串对象创建一个新的相同的字符串对象,将这个新字符串对象的引用赋给新拷贝的Person对象的name字段。这两种拷贝方式分别叫做浅拷贝和深拷贝。
具体的深拷贝、浅拷贝可以参看后面的网址,博主讲的很详细:http://blog.csdn.net/zhangjg_blog/article/details/18369201
最后,希望大家共同进步!坚持做一件事你终会成功!