总体来说设计模式分为三大类
创建型(5种):主要用于处理对象的创建,实例化对象:
单例,建造者,原型,工厂方法,抽象工厂
结构型(7种):处理类或对象间的组合
适配器,装饰者,结合,桥接,外观,享元,代理
行为型(11种):描述类或对象怎样进行交互和职责分配
策略,观察者,迭代器,命令,备忘录,中介者,解释器,访问者,责任链,状态,模板方法
单例模式作用,保证类在内存中的对象唯一性。
适用场景:
饿汉与懒汉的区别
前者在类装载时就实例化,后者只有在第一次被使用时才实例化。 (饿汉的优点是避免线程同步问题,缺点是即使没用到这个实例还是会加载) (懒汉的优点是实现了懒加载,但需要解决线程安全问题!)
1> 饿汉式,没有实现懒加载~
public class Singleton() {
private static Singleton instance = new Singleton();
private Singleton(){ }
public static Singleton getInstance() {
return instance;
}
}
//获取单例对象
Singleton mSingleton = Singleton.getInstance();
2> 懒汉,不加锁 线程非安全的
public class Singleton {
private static Singleton instance = null;
private Singleton() { }
private static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
3> 懒汉,加锁
public class Singleton {
private static Singleton instance = null;
private Singleton() { }
private static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
4>、 静态内部类实现单例(推荐)
public class Singleton {
private Singleton() { }
private static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton()
}
}
5>、 容器类单例模式
public class SingletonManager {
private static Map objMap = new HashMap();
private Singleton(){ }
public static void registerService(String key,Object instance) {
if(!objMap.containsKey(key)) {
objMap.put(key,instance);
}
}
public static Object getService(String key) {
return objMap.get(key);
}
}
原型模式可以通过一个对象实例确定创建对象的种类,并且通过拷贝创建新的实例。总得来说,原型模式实际上就是从一个对象创建另一个新的对象,使新的对象有具有原对象的特征。
原型模式是一种应用及其广泛的设计模式,Clone也是一种十分常见的操作,以至于在Java中,终极父类Object将Clone方法作为了所有类应具有的基本功能,并且Java也提供了Cloneable接口
创建一个原型类, 实现Cloneable 接口(该接口里面是空的,只是起标识作用),并重写clone方法(Object 方法里集成了clone方法)
import java.io.*;
public class CloneableClass implements Cloneable ,Serializable{
public Prototype prototype; // 随便定义一个类,获取实例
public int num;
public String name;
public CloneableClass(Prototype prototype,int num,String name){
this.prototype = prototype;
this.num = num;
this.name = name;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
创建一个执行类
public class CloneableDemo {
public static void main(String[] args) throws Exception{
Prototype prototype = new Prototype();
int num = 10;
String name = "panlei";
CloneableClass cloneableClass = new CloneableClass(prototype,num,name);
System.out.println(cloneableClass.toString());
CloneableClass cloneableClass1 = (CloneableClass)cloneableClass.clone();
System.out.println(cloneableClass.prototype == cloneableClass1.prototype);
System.out.println(cloneableClass.num == cloneableClass1.num);
System.out.println(cloneableClass.name == cloneableClass1.name);
}
}
打印出的结果都为True,说明clone 出的对象属性都是引用的模型的属性;
那么浅拷贝会造成什么样的后果呢?由于浅拷贝仅将字段的引用值复制给了新的字段,但是却并没有创建新的相应对象,也就是说原型和clone中的两个字段都指向了同一个对象实例。这样,我们对clone中各字段所指向对象的属性进行了修改,原型中的成员对象也会随之改变
这时候我们需要clone一个实例,操作时并且不影响原型,这种克隆模式通常称为深克隆
import java.io.*;
public class CloneableClass implements Cloneable ,Serializable{
public Prototype prototype; // 随便定义一个类,获取实例
public int num;
public String name;
public CloneableClass(Prototype prototype,int num,String name){
this.prototype = prototype;
this.num = num;
this.name = name;
}
public Object clone() {
try {
//将对象写到流里
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//从流里读回来
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
原型模式可以说是所有设计模式中最简单的一个,它没有复杂的继承体系,只需要使需要具有拷贝功能的类实现Cloneable接口并重写clone()方法即可。但它的应用却及其广泛,它将对一个对象中各个字段(不管是私有的还是共有的)的复制操作封装在了clone()方法中,这样,使用该类的用户就不需要对对象中的各个字段的细节进行了解,直接调用clone()方法就可以实现对象的拷贝,而且,通过clone()方法还可以为不同的字段设置被复制的权限,从而允许仅对可以被复制的字段进行复制。