版权声明:本文为博主原创文章,未经博主允许不得转载。 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();
}
}
结果如下