简介:
开闭原则
今天来说一下设计模式的6大原则之一的开闭原则。开闭原则是由勒兰特·梅耶在1988年的著作《面向对象软件构造》中首先提出的,其中提到了开闭原则的定义:对扩展开放,对修改关闭。即在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。
那么开闭原则怎么实现呢?可以通过“抽象约束、封装变化”来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。
原型模式:
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
原型模式的运用场景一般分为两种:
- 防止自己的实例在传入别的模块后,发生意外的修改。进行一次拷贝,再将该实例传递给别的模块,可以有效的避免意外的篡改,始终保持该实例的原始性。
- 为了提高效率,很多时候我们需要大量的获取一个对象相同的实例,通过原型模式“克隆”出一个内部属性一样的对象是个好的选择,因为类的初始化需要耗费很多的资源。
Android中的使用:
原型模式在android中有很多运用,如常见的Intent就实现了原型模式。
Intent intent = new Intent(PrototypeDesignActivity.this,BuilderDesignActivity.class);
Intent cloneIntent = (Intent) intent.clone();
那么原型模式是如何实现的呢?首先需要对该类实现Cloneable接口,接着去重写clone()方法,最后在clone()方法中实现类的拷贝。
public class Intent implements Parcelable, Cloneable {
......
@Override
public Object clone() {
return new Intent(this);
}
......
}
需要注意的是,重写的clone()方法并不是Cloneable接口中的,因为该接口是一个空接口。
/**
* @author unascribed
* @see java.lang.CloneNotSupportedException
* @see java.lang.Object#clone()
* @since JDK1.0
*/
public interface Cloneable {
}
其实通过Cloneable接口的注释我们也能知道clone()方法是来自于Object类。并告诉我们有关重写此方法的详细信息请参见Object.clone()方法。
/**
* @return a clone of this instance.
* @exception CloneNotSupportedException if the object's class does not
* support the {@code Cloneable} interface. Subclasses
* that override the {@code clone} method can also
* throw this exception to indicate that an instance cannot
* be cloned.
* @see java.lang.Cloneable
*/
protected Object clone() throws CloneNotSupportedException {
if (!(this instanceof Cloneable)) {
throw new CloneNotSupportedException("Class " + getClass().getName() +
" doesn't implement Cloneable");
}
return internalClone();
}
内容很简单,首先判断是否实现了Cloneable接口,如果没有实现就重写此方法,最终会抛出CloneNotSupportedException异常。如果实现过这个类最终返回internalClone()方法。
/*
* Native helper method for cloning.
*/
private native Object internalClone();
最终我们可以看到这是一个native方法,用于辅助clone。
补充:
深拷贝与浅拷贝
我们知道java中分为基本数据类型和引用数据类型,深浅拷贝就是针对引用数据类型所说的。举个栗子:假如我们用对象A的clone()方法复制了对象B。这时候我们修改A中的某个引用数据类型的属性,这个时候B也跟着改变了,那么这种拷贝方式就是浅拷贝,如果B相对于A是独立的对象,不受到A中任何属性的影响,即A,B中相同的引用所指的地址不同,那么这种就是深拷贝。
常用的实现深拷贝的方式有:递归、利用JSON转换对象、利用Serializable或者Parcelable实现序列化来实现。