工厂饿汉式单例模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36892341/article/details/83617650

先说一下单例模式,单例模式有两种,一种时懒汉式(有线程安全问题),另一种式饿汉式(无线程安全问题)。

懒汉式可以通过加锁解决安全问题,如下两端代码,第一段式有线程安全问题的,一年前lz去面试被要求手写单例模式的时候就是这样写的,被面试官狠狠的鄙视了一波。

package test;
/**
 * @author mzl
 *
 */
public class Singleton {
    private static Singleton instance=null;
    private Singleton(){
        
    }
    public static Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }
}

经过面试官指正后,加锁

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

接下来把单例用到工厂模式式去,比如我们工厂模式要生产one、tow、three三个对象,我们可以定义一个接口,让它们都实现这个接口,同时为了代码更容易维护,使用注解方式,来标记以上三个类。

一、定义一个接口

public interface Strategy {
	
	public String str1(int id1,int id2);
	
	public String str2();

}

二、自定义一个注解

@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Pay {
	int channlId();
}

@Reteniton的作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中

  • SOURCE 
    被编译器忽略

  • CLASS 
    注解将会被保留在Class文件中,但在运行时并不会被VM保留。这是默认行为,所有没有用Retention注解的注解,都会采用这种策略。

  • RUNTIME 

@Target表示作用什么地方。

  • 保留      1.CONSTRUCTOR:用于描述构造器
        2.FIELD:用于描述域
        3.LOCAL_VARIABLE:用于描述局部变量
        4.METHOD:用于描述方法
        5.PACKAGE:用于描述包
        6.PARAMETER:用于描述参数
        7.TYPE:用于描述类、接口(包括注解类型) 或enum声明至运行时。所以我们可以通过反射去获取注解信息。

三、one、tow、three三个类代码如下

@Pay(channlId = 1)
public class One implements Strategy{

	@Override
	public String str1(int id1, int id2) {
		return null;
	}

	@Override
	public String str2() {
		return "one";
	}

}





@Pay(channlId = 3)
public class Two implements Strategy{

	@Override
	public String str1(int id1, int id2) {
		return null;
	}

	@Override
	public String str2() {
		return "two";
	}

}


@Pay(channlId = 2)
public class Three implements Strategy{

	@Override
	public String str1(int id1, int id2) {
		return null;
	}

	@Override
	public String str2() {
		return "three";
	}

}


四、市场工厂单例模式去生成以上三个类

    public class TestFactory {
    	

		private TestFactory() {
		}
		
		//饿汉式
		private  static class  SingletonTest{	
			private final static TestFactory testFactory=new TestFactory();
		}
		
		
		public static TestFactory getTestFactory(){
			return SingletonTest.testFactory;
		}
		
		
       //存放class路径
		public static Map<Integer,String> map=new HashMap<Integer, String>();
		
		
		static{
			//通过注解,把map自动维护
			Reflections reflections=new Reflections("testsunmet.imp.*");
			//获取有Pay注解的class
			Set<Class<?>> classes=reflections.getTypesAnnotatedWith(Pay.class);

			for(Class<?> cl:classes){
				Pay pay=cl.getAnnotation(Pay.class);
				map.put(pay.channlId(), cl.getCanonicalName());
			}
		}
		
		
		//具体生产方法
		public Strategy create(Integer id) throws Exception{
			String clazz=map.get(id);
			Class clazz2=Class.forName(clazz);
			return (Strategy) clazz2.newInstance();
		}
		


 
    }

五、测试看看生成出来的对象

public class TestMain {
	
	public static void main(String arg[]){
		try {
			Strategy one=TestFactory.getTestFactory().create(1);
			System.out.println("这是"+one.str2());
			
			
			Strategy two=TestFactory.getTestFactory().create(2);
			System.out.println("这是"+two.str2());
			
			
			
			Strategy three=TestFactory.getTestFactory().create(3);
			System.out.println("这是"+three.str2());
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

结果如下

猜你喜欢

转载自blog.csdn.net/qq_36892341/article/details/83617650
今日推荐