개인 구조기나 매거 형식으로 단일 예(Singleton) 속성 강화 - Effective Java 소결 (3)

4952 단어
사유 구조기나 매거 유형의 목적은 모두 단례를 확보하기 위한 것이다.그러나 객체를 반사 및 반시퀀스로 작성하려면 추가 작업이 필요합니다.
하나.매거진 형식이 아닌 단일 사례 (1) 는 Serializable의 서열화를 방지하고, 반서열화는 단일 사례를 파괴합니다. ReadResolve 방법을 설명해야 합니다. ObjectInputStream.readObject()가 반환하는 객체는 readResolve의 반환 객체입니다.ps: 실제적으로 새로운 대상을 반서열화한 후에 이 대상의readResolve 방법을 호출했습니다.
public class Singleton_3_1 implements Serializable{

    private static final long serialVersionUID = 1L;
    
    private static final Singleton_3_1 INSTANCE = new Singleton_3_1();
    private Singleton_3_1() {
        
    }
    private String param1;
    public static Singleton_3_1 getInstance() {
        return INSTANCE;
    }
    
    public String getParam1() {
        return param1;
    }
    public void setParam1(String param1) {
        this.param1 = param1;
    }
    
    //keep singleton for deserialization
    private Object readResolve() {
        System.err.println("readResolve :" + (this == INSTANCE));
        return INSTANCE;
    }
    
}

테스트 코드
        public static void testSingleton() throws IOException, ClassNotFoundException {
            Singleton_3_1 singleton1 = Singleton_3_1.getInstance();
            Singleton_3_1 singleton2 = Singleton_3_1.getInstance();
            System.err.println("get instatnce objs == result is " + (singleton1 == singleton2));
            
            Singleton_3_1 singleton3 = Singleton_3_1.getInstance();
            singleton3.setParam1("test");
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(singleton3);
            String objStr = byteArrayOutputStream.toString("ISO-8859-1");
            objectOutputStream.close();
            byteArrayOutputStream.close();
            
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(objStr.getBytes("ISO-8859-1"));
            ObjectInputStream objInputStream = new ObjectInputStream(byteArrayInputStream);
            Singleton_3_1 singleton4 = (Singleton_3_1)objInputStream.readObject();
            objInputStream.close();
            byteArrayInputStream.close();
            
            System.err.println("deserialization objs == result is " + (singleton3 == singleton4));
            System.err.println(singleton4.getParam1());
        }

결과:
get instatnce objs == result is true
readResolve :false
deserialization objs == result is true
test

readObject 호출 프로세스
1.ObjectInputStream.readObject();
2.ObjectInputStream.readObject0();
3.ObjectInputStream.readOrdinaryObject(unshared);
        if (obj != null &&
            handles.lookupException(passHandle) == null &&
            desc.hasReadResolveMethod())
        {
            Object rep = desc.invokeReadResolve(obj);
            if (unshared && rep.getClass().isArray()) {
                rep = cloneArray(rep);
            }
            if (rep != obj) {
                // Filter the replacement object
                if (rep != null) {
                    if (rep.getClass().isArray()) {
                        filterCheck(rep.getClass(), Array.getLength(rep));
                    } else {
                        filterCheck(rep.getClass(), -1);
                    }
                }
                handles.setObject(passHandle, obj = rep);
            }
        }

        return obj;


(2) 반사 파괴 방지 예: 구조기를 수정하여 추가 실례를 만들 때 이상을 던집니다.
    private Singleton_3_1() {
        if (null != INSTANCE) {
            throw new RuntimeException();
        }
    }

Client:
        //1. private , 
//      Singleton_3_1 singleton5 = (Singleton_3_1) c.newInstance();
        //2. private , 
//      Constructor constructor1 = c.getDeclaredConstructor();
//      Object obj1 = constructor1.newInstance();
        //3. private , 。
        Constructor constructor2 = c.getDeclaredConstructor();
        constructor2.setAccessible(true);
        Object obj2 = constructor2.newInstance();

둘.매거 유형이 실현된 단례는 new,clone (), de-serialization, 그리고 Reflection API를 이용하여 enum의 instance를 만들 수 없습니다.
public enum Singleton_3_2 {
    INSTANCE;
    private int num;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
    
}

셋.대외 공개 단례의 대상은 다음과 같다.단일 속성 공개 가능public static final Singleton INSTANCE = nwe Singleton()2. 단일 속성을 획득하는 방법도 공개할 수 있다
private static final Singleton INSTANCE = nwe Singleton();
public static Singleton getInstance() {
    return INSTANCE;
}

이런 방식은 이전의 방식보다 더욱 유연하다. 왜냐하면 이 방법의 실현을 쉽게 수정할 수 있고 호출자에게 영향을 주지 않기 때문이다.
총괄: 매거 유형으로 단례를 실현한다. 단원소의 매거 유형은 단례를 실현하는 가장 좋은 방법이다.

좋은 웹페이지 즐겨찾기