常用设计模式之单例模式和工厂模式
-
单例模式
一 : 懒汉式 单例 1. //懒汉式单例类.在第一次调用的时候实例化自己 2. public class Singleton { 3. private Singleton() {} 4. private static Singleton single=null; 5. //静态工厂方法 6. public static Singleton getInstance() { 7. if (single == null) { 8. single = new Singleton(); 9. } 10. return single; 11. } 12. } 1、在getInstance方法上加同步 1. public static synchronized Singleton getInstance() { 2. if (single == null) { 3. single = new Singleton(); 4. } 5. return single; 6. } 2、双重检查锁定 1. public static Singleton getInstance() { 2. if (singleton == null) { 3. synchronized (Singleton.class) { 4. if (singleton == null) { 5. singleton = new Singleton(); 6. } 7. } 8. } 9. return singleton; 10. } 3、静态内部类 1. public class Singleton { 2. private static class LazyHolder { 3. private static final Singleton INSTANCE = new Singleton(); 4. } 5. private Singleton (){} 6. public static final Singleton getInstance() { 7. return LazyHolder.INSTANCE; 8. } 9. } 二: 饿汉式单例 1. /饿汉式单例类.在类初始化时,已经自行实例化 2. public class Singleton1 { 3. private Singleton1() {} 4. private static final Singleton1 single = new Singleton1(); 5. //静态工厂方法 6. public static Singleton1 getInstance() { 7. return single; 8. } 9. }饿汉式和懒汉式区别 从名字上来说,饿汉和懒汉, 饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。另外从以下两点再区分以下这两种方式: 1、线程安全: 饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题, 懒汉式本身是非线程安全的,为了实现线程安全有几种写法,分别是上面的1、2、3,这三种实现在资源加载和性能方面有些区别。 2、资源加载和性能: 饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成, 而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。 至于1、2、3这三种实现又有些区别, 第1种,在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的, 第2种,在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗 第3种,利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。
-
工厂模式
1. abstract class BMW { 2. public BMW(){ 3. 4. } 5. } 6. public class BMW320 extends BMW { 7. public BMW320() { 8. System.out.println("制造-->BMW320"); 9. } 10. } 11. public class BMW523 extends BMW{ 12. public BMW523(){ 13. System.out.println("制造-->BMW523"); 14. } 15. } 创建工厂类: 1. interface FactoryBMW { 2. BMW createBMW(); 3. } 4. 5. public class FactoryBMW320 implements FactoryBMW{ 6. 7. @Override 8. public BMW320 createBMW() { 9. 10. return new BMW320(); 11. } 12. 13. } 14. public class FactoryBMW523 implements FactoryBMW { 15. @Override 16. public BMW523 createBMW() { 17. 18. return new BMW523(); 19. } 20. } 客户类: 1. public class Customer { 2. public static void main(String[] args) { 3. FactoryBMW320 factoryBMW320 = new FactoryBMW320(); 4. BMW320 bmw320 = factoryBMW320.createBMW(); 5. 6. FactoryBMW523 factoryBMW523 = new FactoryBMW523(); 7. BMW523 bmw523 = factoryBMW523.createBMW(); 8. } 9. }工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有 的代码。可以看出工厂角色的结构也是符合开闭原则的!
更多精彩