单例模式 工厂模式

单例模式:确保某类只有一个实例,并且向整个程序或系统提供这个实例,大多时候应用于工具类,或者管理调度相关的类。

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton(){}

    public static Singleton getInstance(){
        return instance;
    }
}

把构造方法设为私有,通过类静态方法来获取静态变量。由于是在类加载时候就生成的实例,所以线程安全,调用迅速。

public class Singleton {
private Singleton() {}
private static Singleton single=null; 
    public static Singleton getInstance() {
         if (single == null) {  
             single = new Singleton();
         }  
        return single;
    }  
}

调用类方法实例化类,但是在多线程的时候可能会出现多个实例对象。处理方法加synchronized关键字实现同步处理。

1.public static synchronized Singleton getInstance() {
     if (single == null) {  
         single = new Singleton();
     }  
    return single;
 }
2. public static Singleton getInstance() {
    if (singleton == null) {  
        synchronized (Singleton.class) {  
           if (singleton == null) {  
              singleton = new Singleton(); 
           }  
        }  
    }  
    return singleton; 
}

两种都是加synchronized关键字来实现线程同步,但是作用的位置不同。在单利中我们只是要在获取实例的时候保持同步,只有在第一次的时候才会生成实例,那么反之,在获取实例的时候如果不是第一次获取,直接返回实例即可,如果是第一次获取,那么久要生成实例再返回实例对象,所以第二种方法要比第一种方法更合理。

public class Singleton {  
        private static class LazyHolder {  
           private static final Singleton INSTANCE = new Singleton();  
        }  
        private Singleton (){}  
        public static final Singleton getInstance() {  
           return LazyHolder.INSTANCE;  
        }   
}  

静态内部类,看起来像是前面两种方法的结合体。既实现了线程安全,又避免了同步带来的性能影响。但实际上还是要根据实际情况来确定到底使用哪种方法。
枚举

public enum Singleton {
    INSTANCE;
    private Singleton() {}

}

Java规范中规定,每一个枚举类型极其定义的枚举变量在JVM中都是唯一的,所以枚举来实现单例是再合适不过的了。
当然所有的单例模式在你使用反射的时候就会破坏单例的结构。因为反射的”身份”比较高级。

工厂模式

简单工厂,简单工厂就是一个生成实例的特殊类,他在自己内部处理简单的实例生成逻辑,从而生成需要的实例。简单工厂的就是简单,他只能应用于逻辑关系,依赖关系都比较简单的情况下。

public class Factory {

    public static MyClass GetClass(int conditions){
        MyClass m = null;
        switch (conditions){
            case 1:  m = new A();
            case 2 :  m = new B();
            case 3:  m = new C();
            case 4 :  m = new D();
            default:break;
        }
        return m;
    }
}

工厂方法,主要区别于简单工厂的是,他不需要自己进行逻辑处理,他把实例的生成延迟到子类。下面是大话设计模式中的简单示例。

//定义上级工厂的接口
public interface IFractory {
    public Operation generateOper();
}
//为每一个类创建工厂
/**
 * 工厂方法  为每个对象生成一个工厂类
 */
public class AddOperationFactory implements IFractory{

    @Override
    public Operation generateOper() {
        return new AddOperation();
    }
}
public class SubOperationFactory implements IFractory {
    @Override
    public Operation generateOper() {
        return new SubOperation();
    }
}
public class MulOperationFactory implements IFractory {
    @Override
    public Operation generateOper() {
        return new MulOperation();
    }
}
public class DivOperationFactory implements IFractory {
    @Override
    public Operation generateOper() {
        return new DivOperation();
    }
}
//客户端代码
IFractory fractory = new AddOperationFactory();
Operation operation = fractory.generateOper();
operation.getResult(firstNum,secondNum);

抽象工厂,依赖接口,不需要知道具体的实现类。主要用于多种产品族的切换,但是在增加的时候会出现大量重复的逻辑和代码。

public interface IFacfory {
    public IUser createUser();
    public IDepartment createDepartment();
}
public interface IUser {
    public void insert();
    public void getById();
}
public interface IDepartment {
    public void insert();
    public void getDepartmentById();
}
public class SqlServerUser implements IUser {
    @Override
    public void insert() {
        System.out.println("insert into sqlserver.");
    }

    @Override
    public void getById() {
        System.out.println("get user by id from sqlserver.");
    }
}
public class SqlServerDepartment implements IDepartment {
    @Override
    public void insert() {
        System.out.println("insert department into sqlserver.");
    }

    @Override
    public void getDepartmentById() {
        System.out.println("get department in sqlserver by id.");
    }
}

public class AccessUser implements IUser {
    @Override
    public void insert() {
        System.out.println("insert into access");
    }

    @Override
    public void getById() {
        System.out.println("get by id from access");
    }
}
public class AccessDepartment implements IDepartment {
    @Override
    public void insert() {
        System.out.println("insert department into sqlserver.");
    }

    @Override
    public void getDepartmentById() {
        System.out.println("get department in sqlserver by id.");
    }
}
//不同产品组使用一个工厂
public class SqlServerFactory implements IFacfory {
    @Override
    public IUser createUser() {
        return new SqlServerUser();
    }

    @Override
    public IDepartment createDepartment() {
        return new SqlServerDepartment();
    }
}
public class AccessFactory implements IFacfory {
    @Override
    public IUser createUser() {
        return new AccessUser();
    }

    @Override
    public IDepartment createDepartment() {
        return new AccessDepartment();
    }
}
客户端:
IFacfory facfory = new AccessFactory();
IUser user = facfory.createUser();
IDepartment department = facfory.createDepartment();
user.insert();
user.getById();
department.insert();
department.getDepartmentById();

利用反射+抽象工厂,或者反射和配置文件可以提升其性能。这两种方法在某种程度上灵活性更高,主要是在实例对象的获取上提供更换方便的作用。(虽然听起来很牛逼,使用很简单,但具体实践中还没用到过这种模式,汗颜。)如果以后使用到,体会到其中玄妙,会再次补充。

MARK(4)

道冲而用之,或不盈。渊兮似万物之宗。解其纷,和其光,同其尘,湛兮似或存。吾不知谁之子,象帝之先。

猜你喜欢

转载自blog.csdn.net/joy_chow/article/details/80653004