在创建一个对象的时候,我们通常会用到以下几个方式:单例模式、工厂模式、建造者模式。我们具体看下怎么使用,以及应用场景。
单例模式
单例模式常见的主要有饿汉模式、懒汉模式、双重检测、静态内部类。
饿汉模式:
public class IdGenerator {
private IdGenerator(){}
private static IdGenerator idGenerator = new IdGenerator();
public static IdGenerator getInstance(){
return idGenerator;
}
}
适用点:预加载,降低在程序过程中初始化慢可能带来的性能问题。适用于初始化加载时间长的对象,缺点不能延迟加载对象。
懒汉模式
public class IdGenerator {
private IdGenerator(){}
private static IdGenerator idGenerator ;
public static synchronized IdGenerator getInstance(){
if(idGenerator==null){
idGenerator = new IdGenerator();
}
return idGenerator;
}
}
适用点:延迟加载,但是由于在加锁,导致并发性不高。适用于使用不频繁,并发量不高的情况
双重检测
public class IdGenerator {
private IdGenerator(){}
private static volatile IdGenerator idGenerator ;
public static IdGenerator getInstance(){
if(idGenerator==null){
synchronized (IdGenerator.class){
if(idGenerator==null){
idGenerator = new IdGenerator();
}
}
}
return idGenerator;
}
}
适用点:既满足了并发量的场景,也满足了延迟加载。双重检测锁的优势在于并发情况下,多条线程同时获取null的情况。
内部静态类
public class IdGenerator {
private IdGenerator(){}
private static class IdGeneratorHolder{
private static IdGenerator idGenerator = new IdGenerator();
}
public static IdGenerator getInstance(){
return IdGeneratorHolder.idGenerator;
}
}
适用点:满足了延迟加载,也没有双重检测写法麻烦。保证了线程的安全性
单例模式主要适用的场景在于当一个类只需要一个实例对象的时候。默认为无参构造函数,当我们为有参构造函数时,实现一个单例,只能通过延迟加载的模式中传入参数
工厂模式
工厂模式主要分为三个:简单工厂模式、工厂模式、抽象工厂模式
简单工厂模式: 主要用途创建对象的过程比较简单,可以直接放置在一个工厂类中,进行判断
工厂模式: 主要用途创建对象的过程比较复杂,则每个对象都有自己的工厂类,然后整合到统一的工厂类中
抽象工厂:主要当创建的对象其实又分为两个或多个大的方向时,则对象在生成自己的工厂类的方法的时候。同时继承同一个方向的接口
普通模式
public void countAninal(String type){
Animal animal=null;
if(type.equalsIgnoreCase("dog")){
animal = new Dog();
}else if(type.equalsIgnoreCase("cat")){
animal = new Cat();
}else if(type.equalsIgnoreCase("chick")){
animal = new Chick();
}
animal.name();
}
简单工厂模式(为了职责单一,将创建对象这块进行剥离,工厂类总是以Factory结尾)
public class Zoo {
public void countAninal(String type){
Animal animal = AninalFacory.getAnimalByType(type);
animal.name();
}
}
class AninalFacory{
public static Animal getAnimalByType(String type){
Animal animal=null;
if(type.equalsIgnoreCase("dog")){
animal = new Dog();
}else if(type.equalsIgnoreCase("cat")){
animal = new Cat();
}else if(type.equalsIgnoreCase("chick")){
animal = new Chick();
}
return animal;
}
}
工厂模式如果在每个类创建的时候比较负责,或者又会对应多种情况,则这个时候用工厂模式呢,为每个类别生成单独的工厂类。抽象工厂则为一个工厂类,可以产生多个类别的对象。
建造者模式
当我们创建一个类的时候,初始化的时候参数列表很冗长时,且创建后,希望参数不在变时。这个时候我们可以采用构造者模式
public class ResourcePool {
private String name;
private String maxTotal;
private String maxIdel;
private String minTotal;
public ResourcePool(ResourcePoolBuilder builder){
this.name = builder.getName();
this.maxTotal = builder.getMaxTotal();
this.maxIdel = builder.getMaxIdel();
this.minTotal = builder.getMinTotal();
}
}
class ResourcePoolBuilder{
private String name;
private String maxTotal;
private String maxIdel;
private String minTotal;
public static ResourcePoolBuilder custom(){
ResourcePoolBuilder resourcePoolBuilder = new ResourcePoolBuilder();
return resourcePoolBuilder;
}
public ResourcePoolBuilder setName(String name){
this.name = name;
return this;
}
public ResourcePoolBuilder setMaxTotal(String maxTotal){
this.maxTotal = maxTotal;
return this;
}
public ResourcePool build(){
return new ResourcePool(this);
}
public String getName() {
return name;
}
public String getMaxTotal() {
return maxTotal;
}
public String getMaxIdel() {
return maxIdel;
}
public String getMinTotal() {
return minTotal;
}
}
原型模型
如果创建一个对象成本太大,而同一个类的不同对象差别不大的时候,这个时候我们用原型模式进行拷贝。拷贝又分为深拷贝和浅拷贝。浅拷贝是指只拷贝引用对象地址,不拷贝对象本身。深拷贝是指既拷贝地址又拷贝对象本身,成为一个独立的对象。
深拷贝的方式一般有:通过代码逻辑进行对象的复制。通过序列化和反序列化形成对象的拷贝。
public Object deepCopyObjec(Object object) throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(object);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
return objectInputStream.readObject();
}
以上为设计模式中的创建型。