-
饿汉式单例
public class Singleton1{ private Singleton1(){} private static final Singleton1 instance=new Singleton1(); public static Singleton1 getInstance { return instance; } }
-
懒汉式单例(线程不安全)
public class Singleton2{ private Singleton2(){} private static Singleton2 instance=null; public static Singleton2 getInstance(){ if(instance==null) { instance=new Singleton2; } else { return instance; } } }
-
懒汉的加锁实现
public class Singleton2{ private Singleton2(){} private static Singleton2 instance=null; public static synchronized Singleton2 getInstance(){ if(instance==null) { instance=new Singleton2; } else { return instance; } } }
-
懒汉的双重判断实现方式
public class Singleton2{ private Singleton2(){} private static Singleton2 instance=null; public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
-
懒汉的内部类实现方式
public class Singleton2{ private Singleton2(){} public class InSingleton{ private static final Singleton2 INSTANCE=new Singleton2(); } public static final Singleton2 getInstance(){ return InSingleton.INSTANCE; } }
内部类实现方式比双重判断和加锁的方法都好
-
-
双判断的懒汉式单例应用
public class TestSingleton { String name = null; private TestSingleton() { } private static volatile TestSingleton instance = null; public static TestSingleton getInstance() { if (instance == null) { synchronized (TestSingleton.class) { if (instance == null) { instance = new TestSingleton(); } } } return instance; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void printInfo() { System.out.println("the name is " + name); } }
对于应用volatile的解释如下:
应该加上volatile关键字,不加的情况下可能发生下面2、3步骤发生指令重排序,所以只是在内存中开辟一片存储对象的内存后直接返回内存的引用,之后instance便不为空了,但实际操作却还没有执行,这时如果B线程进来看到,就会看到一个不为空但是还没有初始化的对象,返回后使用就会出现错误。所以需要给instance加上volatile。
创建对象可以分解为如下的3行伪代码
memory=allocate(); //1:分配对象的内存空间
ctorInstance(memory); //2:初始化对象 instance=memory; //3:设置instance指向刚分配的内存地址 上面3行代码中的2和3之间,可能会被重排序导致先3后2,
-
代码实例
public class Demo1{ public static class LeiFeng { public void Sweep() { System.out.println("扫地"); } public void Wash() { System.out.println("洗"); } public void Buy() { System.out.println("买"); } } public static abstract class IFactory { public abstract LeiFeng CreatLei(); } public static class Student extends LeiFeng { public void Sweep() { System.out.println("1扫地"); } public void Wash() { System.out.println("2洗"); } public void Buy() { System.out.println("3买"); } } public static class Com extends LeiFeng { } public static class StudentFactory extends IFactory { public LeiFeng CreatLei() { return new Student(); } } public static class ComFactory extends IFactory { public LeiFeng CreatLei() { return new Com(); } } public static void main(String[] args) { IFactory factory=new StudentFactory();//只需要在这里修改一行就可以改变继承对象 LeiFeng con=factory.CreatLei(); con.Buy(); con.Sweep(); con.Wash(); } }
-
-
反射+抽象工厂的数据访问程序,实现不用在打码处改就可改变所用数据库,即使加原本没预算的也没关系
//App.config <?xml version="1.0" encoding="utf-8"?> <configuration> <appSettings> <add key="DB" value="Sqlserver"/> </appSettings> </configuration>
private static readonly String db=ConfigurationManager.AppSettings["DB"]; using System.Reflection; //一下写主要步骤,传参为主。 class DataAccess { public static IUser CreatUser() { String className=AssemblyName+"."+db+"User"; return (IUser)Assembly.Load(AssemblyName).CreatInstance(className); } public static IDepartment CreatDepartment() { String className=AssemblyName+"."+db+"Department"; return (IDepartment)Assembly.Load(AssemblyName).CreatInstance(className); } }