单例模式:确保某类只有一个实例,并且向整个程序或系统提供这个实例,大多时候应用于工具类,或者管理调度相关的类。
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)
道冲而用之,或不盈。渊兮似万物之宗。解其纷,和其光,同其尘,湛兮似或存。吾不知谁之子,象帝之先。