Android 에서 자주 사용 하 는 디자인 모드 (1)
개념: 하나의 인 스 턴 스 만 확보 하고 자체 적 으로 예화 하여 전체 시스템 에 전체 인 스 턴 스 를 제공 합 니 다.
장점:
1. 메모리 소모 유형 에 대해 한 번 만 예화 하여 성능 을 크게 향상 시킨다. 특히 모 바 일 개발 에서
2. 프로그램 실행 중 메모리 에 하나의 인 스 턴 스 만 유지 합 니 다.
public class Singleton {  
    private static volatile Singleton instance = null;  
    private Singleton(){  
    }  
    public static Singleton getInstance() {  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                if (instance == null) {  
                    instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }  
}  구조 함수 의 사유 화, 정적 함 수 를 정의 하여 인 스 턴 스 를 얻 는 것 은 더 이상 말 하지 않 겠 습 니 다. 여기 서 volatile 을 다시 말 하 겠 습 니 다.
volatile 본질은 jvm 에 현재 변수 가 레지스터 에 있 는 값 이 불확실 하 다 는 것 을 알려 주 는 것 입 니 다. 메모리 에서 읽 어야 합 니 다. synchronized 는 현재 변 수 를 잠 그 고 현재 스 레 드 만 이 변 수 를 방문 할 수 있 으 며 다른 스 레 드 가 막 혔 습 니 다.(우선 우 리 는 이러한 현상 을 의식 해 야 합 니 다. 컴 파 일 러 는 프로그램 이 실행 되 는 속 도 를 높이 기 위해 일부 변수 에 대한 쓰기 작업 은 레지스터 나 CPU 캐 시 에서 먼저 진행 되 고 마지막 에 메모리 에 기록 합 니 다. 이 과정 에서 변수의 새로운 값 은 다른 스 레 드 에 서 는 볼 수 없습니다. volatile 의 역할 은 변 수 를 수정 하 는 읽 기와 쓰기 작업 을 메모리 에서 해 야 합 니 다!)
그리고 이 이중 판단 null:
이것 은 만약 에 스 레 드 A 가 이 코드 에 들 어가 면 스 레 드 B 가 기다 리 고 있 기 때 문 입 니 다. 이것 은 A 스 레 드 가 하나의 인 스 턴 스 를 만 든 후에 스 레 드 B 가 자 물 쇠 를 얻어 동기 화 코드 에 들 어 갑 니 다. 인 스 턴 스 가 이미 존재 하고 나무 가 다시 만 들 필요 가 있 기 때문에 이중 판단 이 필요 합 니 다.
에이, 말 안 할 게 또 이렇게 많아.
Android 에 사용 되 는 부분 이 많 습 니 다. 예 를 들 어 Android - Universal - Image - oader 의 단일 예, EventBus 의 단일 예 입 니 다.
마지막 으로 우리 activity 를 관리 하 는 클래스 를 드 립 니 다. 간단 한 도구 클래스 로 사용 할 수 있 습 니 다.
public class ActivityManager {  
    private static volatile ActivityManager instance;  
    private Stack mActivityStack = new Stack();  
    private ActivityManager(){  
    }  
    public static ActivityManager getInstance(){  
        if (instance == null) {  
        synchronized (ActivityManager.class) {  
            if (instance == null) {  
                instance = new ActivityManager();  
            }  
        }  
        return instance;  
    }  
    public void addActicity(Activity act){  
        mActivityStack.push(act);  
    }  
    public void removeActivity(Activity act){  
        mActivityStack.remove(act);  
    }  
    public void killMyProcess(){  
        int nCount = mActivityStack.size();  
        for (int i = nCount - 1; i >= 0; i--) {  
            Activity activity = mActivityStack.get(i);  
            activity.finish();  
        }  
        mActivityStack.clear();  
        android.os.Process.killProcess(android.os.Process.myPid());  
    } 
}   빌 더 모드
아니면 순서대로 정의, 인터넷 의 정 의 를 먼저 말 해 보 세 요.
복잡 한 대상 의 구축 과 그 표 시 를 분리 시 켜 같은 구축 과정 에서 서로 다른 표 시 를 만 들 수 있 습 니 다.
올 라 와 서 두 번 읽 어 본 다음 에 못 읽 었 다 는 것 을 알 게 되 었 습 니 다. 괜 찮 습 니 다. 모두 가 거의 읽 지 못 했 습 니 다. 개념 은 추상 적 이 고 이해 하기 어 려 운 것 입 니 다. 이 개념 에서 이 모델 을 간단하게 알 게 된다 면 자 료 를 찾 아 뒤의 물건 을 정리 하 는 데 힘 들 이지 않 아 도 됩 니 다. 여기 서 우 리 는 밤 하 나 를 통 해 Build 모델 을 끌 어 냅 니 다. 가설 에 하나 가 있다 고 가정 합 니 다.Person 류, 그의 일부 속성 은 null 일 수 있 습 니 다. 이 종 류 를 통 해 많은 사람 을 구성 할 수 있 습 니 다.
public class Person {  
    private String name;  
    private int age;  
    private double height;  
    private double weight;  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public int getAge() {  
        return age;  
    }  
    public void setAge(int age) {  
        this.age = age;  
    }  
    public double getHeight() {  
        return height;  
    }  
    public void setHeight(double height) {  
        this.height = height;  
    }  
    public double getWeight() {  
        return weight;  
    }  
    public void setWeight(double weight) {  
        this.weight = weight;  
    }  
}  
그리고 편 의 를 위해 서 당신 은 이러한 구조 함 수 를 써 서 속성 을 입 을 수 있 습 니 다.
public Person(String name, int age, double height, double weight) {  
    this.name = name;  
    this.age = age;  
    this.height = height;  
    this.weight = weight;  
} 아니면 좀 더 편리 하 게 빈 구조 함 수 를 쓸 수도 있어 요.
public Person() {  
} 때로는 게 으 르 고 일부 매개 변수 만 들 어 오고 구조 함수 도 쓴다.
public Person(String name) {  
    this.name = name;  
}  
public Person(String name, int age) {  
    this.name = name;  
    this.age = age;  
}  
public Person(String name, int age, double height) {  
    this.name = name;  
    this.age = age;  
    this.height = height;  
} 그래서 필요 한 종 류 를 만 들 수 있 습 니 다.
Person p1=new Person();  
Person p2=new Person("  ");  
Person p3=new Person("  ",18);  
Person p4=new Person("  ",21,180);  
Person p5=new Person("  ",17,170,65.4);사실 이런 쓰기 의 나 쁜 점 은 당신 이 쓰 는 과정 에서 키 보드 를 떨 어 뜨리 려 고 할 때 생각해 야 합 니 다. 대상 을 만 드 는 과정 인 데 왜 이렇게 번 거 롭 고 구조 함수 파라미터 가 너무 많 습 니까? 다른 사람들 이 대상 을 만 들 때 각 매개 변수 가 무슨 뜻 을 의미 하 는 지 어떻게 알 겠 습 니까? 이때 우 리 는 코드 의 가 독성 을 위해 Builder 모드 를 사용 하여 Pers 에 게 줄 수 있 습 니 다.on 클래스 에 정적 Builder 클래스 를 추가 한 다음 Person 의 구조 함 수 를 수정 합 니 다. 다음 과 같 습 니 다.
public class Person {  
    private String name;  
    private int age;  
    private double height;  
    private double weight;  
    privatePerson(Builder builder) {  
        this.name=builder.name;  
        this.age=builder.age;  
        this.height=builder.height;  
        this.weight=builder.weight;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public int getAge() {  
        return age;  
    }  
    public void setAge(int age) {  
        this.age = age;  
    }  
    public double getHeight() {  
        return height;  
    }  
    public void setHeight(double height) {  
        this.height = height;  
    }  
    public double getWeight() {  
        return weight;  
    }  
    public void setWeight(double weight) {  
        this.weight = weight;  
    }  
    static class Builder{  
        private String name;  
        private int age;  
        private double height;  
        private double weight;  
        public Builder name(String name){  
            this.name=name;  
            return this;  
        }  
        public Builder age(int age){  
            this.age=age;  
            return this;  
        }  
        public Builder height(double height){  
            this.height=height;  
            return this;  
        }  
        public Builder weight(double weight){  
            this.weight=weight;  
            return this;  
        }  
        public Person build(){  
            return new Person(this);  
        }  
    }  
}  위의 코드 에서 우 리 는 Builder 클래스 에서 Person 클래스 와 같은 속성 을 정의 하고 일련의 구성원 함 수 를 통 해 값 을 부여 하 는 것 을 볼 수 있 습 니 다. 그러나 돌아 오 는 것 은 모두 this 입 니 다. 마지막 으로 build 함 수 를 제공 하여 person 대상 을 만 들 었 습 니 다. 이에 대응 하 는 Person 의 구조 함수 에 Builder 대상 을 전송 한 다음 에 자신의 구성원 변 수 를 순서대로 할당 합 니 다. 그 밖 에Builder 의 구성원 함수 가 돌아 오 는 것 은 모두 this 의 또 다른 역할 은 바로 그 로 하여 금 체인 호출 을 지원 하 게 하고 코드 의 가 독성 을 크게 향상 시 키 는 것 이다. 그래서 우 리 는 이렇게 Person 대상 을 만 들 수 있다.
Person.Builder builder=new Person.Builder();  
Person person=builder  
        .name("  ")  
        .age(18)  
        .height(178.5)  
        .weight(67.4)  
        .build();  약간 그런 느낌 이 들 지 않 나 요? Android 에서 Builder 모드 를 많이 사 용 했 습 니 다. 예 를 들 어 흔히 볼 수 있 는 대화 상자 생 성 등 입 니 다.
AlertDialog.Builder builder=new AlertDialog.Builder(this);  
AlertDialog dialog=builder.setTitle("  ")  
        .setIcon(android.R.drawable.ic_dialog_alert)  
        .setView(R.layout.myview)  
        .setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  
            }  
        })  
        .setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  
            }  
        })  
        .create();  
dialog.show();  사실 자바 에 서 는 StringBuilder 와 StringBuffer 가 모두 Builder 모드 를 사 용 했 습 니 다. Gson 의 Gson Builder 에 서 는 조금 간단 할 뿐 입 니 다.
GsonBuilder builder=new GsonBuilder();  
Gson gson=builder.setPrettyPrinting()  
        .disableHtmlEscaping()  
        .generateNonExecutableJson()  
        .serializeNulls()  
        .create(); 네트워크 프레임 워 크 OKHttp
Request.Builder builder=new Request.Builder();  
Request request=builder.addHeader("","")  
    .url("")  
    .post(body)  
    .build();  대량의 프레임 워 크 가 Builder 디자인 모델 을 활용 한 것 을 알 수 있 습 니 다. 정리 해 보 세 요.
정적 내부 클래스 Builder 를 정의 합 니 다. 내부 구성원 변 수 는 외부 와 마찬가지 로 Builder 는 일련의 방법 으로 구성원 변수 에 값 을 부여 하고 현재 대상 (this) 을 되 돌려 줍 니 다.Builder 클래스 내부 에서 build 방법 이나 create 방법 을 제공 하여 해당 하 는 외부 클래스 를 만 드 는 데 사용 합 니 다. 이 방법 은 내부 에서 외부 클래스 의 사유 화 구조 방법 을 호출 했 습 니 다. 이 구조 방법의 매개 변 수 는 내부 클래스 Builder 외부 클래스 가 내부 클래스 를 호출 할 수 있 도록 사유 화 된 구조 방법 을 제공 하 는 것 입 니 다. 이 구조 함수 에서 구성원 변수의 할당 을 완성 합 니 다.
관찰자 모드
두말 하지 않 고 올 라 오 면 정의 다.
대상 간 의 다 중 의존 관 계 를 정의 합 니 다. 대상 의 상태 가 바 뀌 었 을 때 모든 의존 대상 은 알림 을 받 고 자동 으로 업 데 이 트 됩 니 다.
이 건 조금 은 이해 할 수 있 을 것 같 지만 상황 부터 말씀 드 리 겠 습 니 다.
일기예보 의 문자 서 비 스 는 일단 비용 을 지불 하고 구독 하면 매번 날씨 가 업 데 이 트 될 때마다 당신 에 게 제때에 보 냅 니 다.
사실은 우리 가 매 순간 우리 가 관심 이 있 는 것 에 관심 을 가 질 필요 가 없다 는 것 이다. 우 리 는 그것 을 구독 하면 된다. 우리 가 구독 하 는 업무 가 변화 하면 구독 하 는 업 무 는 즉시 우리 에 게 알려 줄 것 이다.
관찰자 모드 의 구성 을 살 펴 보 자.
관찰자 모델 의 구체 적 인 실현 에 대해 자바 에 서 는 Observable 류 와 Observer 인 터 페 이 스 를 제공 하여 이 모델 을 신속하게 실현 할 수 있 도록 해 주 었 습 니 다. 그러나 여기 서 인상 을 깊 히 기 위해 이 두 가지 유형 을 사용 하지 않 고 위의 장면 을 모 의 하여 Weather 류 를 정의 합 니 다.
public class Weather {  
    private String description;  
    public Weather(String description) {  
        this.description = description;  
    }  
    public String getDescription() {  
        return description;  
    }  
    public void setDescription(String description) {  
        this.description = description;  
    }  
    @Override  
    public String toString() {  
        return "Weather{" +  
                "description='" + description + '\'' +  
                '}';  
    }  
}  그 다음 에 우리 의 관찰 을 정의 합 니 다. 우 리 는 그것 이 통용 되 기 를 바 랍 니 다. 그래서 범 형 으로 정의 합 니 다. 내부 에 register 와 unRegister 가 관찰자 의 구독 과 구독 취 소 를 제공 해 야 합 니 다. 관찰자 의 저장 에 대해 우 리 는 Array List 를 사용 하면 됩 니 다. 또한 주제 가 변화 할 때 관찰자 에 게 응답 을 알려 야 합 니 다. notify Observer 방법 도 필요 합 니 다. 구체 적 인 방법 도 필요 합 니 다.다음 과 같이 구현:
public class Observable {  
    List> mObservers = new ArrayList>();  
    public void register(Observer observer) {  
        if (observer == null) {  
            throw new NullPointerException("observer == null");  
        }  
        synchronized (this) {  
            if (!mObservers.contains(observer))  
                mObservers.add(observer);  
        }  
    }  
    public synchronized void unregister(Observer observer) {  
        mObservers.remove(observer);  
    }  
    public void notifyObservers(T data) {  
        for (Observer observer : mObservers) {  
            observer.onUpdate(this, data);  
        }  
    }  
}        그리고 우리 의 관찰 자 는 한 관찰자 의 인터페이스 Observer 만 실현 해 야 한다. 이 인터페이스 도 일반적이다.
public interface Observer {  
    void onUpdate(Observable observable,T data);  
}    구독 주제 에 변화 가 생기 면 이 인 터 페 이 스 를 사용 합 니 다. 우 리 는 날씨 변화의 주 제 를 정의 합 니 다. 즉, 피 관찰 자 를 정의 하고 두 관찰 자 를 정의 하여 날씨의 변 화 를 관찰 합 니 다. 변화 가 생기 면 날씨의 상황 을 인쇄 합 니 다. 주의 하 세 요. 반드시 register 방법 으로 등록 해 야 합 니 다. 그렇지 않 으 면 관찰자 가 변화 하 는 정 보 를 받 지 못 하고 관심 이 없 으 면unregister 방법 을 호출 할 수 있 습 니 다.
public class Main {  
    public static void main(String [] args){  
        Observable observable=new Observable();  
        Observer observer1=new Observer() {  
            @Override  
            public void onUpdate(Observable observable, Weather data) {  
                System.out.println("   1:"+data.toString());  
            }  
        };  
        Observer observer2=new Observer() {  
            @Override  
            public void onUpdate(Observable observable, Weather data) {  
                System.out.println("   2:"+data.toString());  
            }  
        };  
        observable.register(observer1);  
        observable.register(observer2);  
        Weather weather=new Weather("    ");  
        observable.notifyObservers(weather);  
        Weather weather1=new Weather("    ");  
        observable.notifyObservers(weather1);  
        observable.unregister(observer1);  
        Weather weather2=new Weather("  ");  
        observable.notifyObservers(weather2);  
    }  
}          출력 도 꺼 짐 문제 관찰자 1: Weather {description = '맑 음 에서 구름 이 많아 짐'} 관찰자 2: Weather {description = '맑 음 에서 구름 이 많아 짐'} 관찰자 1: Weather {description = '구름 이 많아 지면 흐 림'} 관찰자 2: Weather {description = '구름 이 많아 지면 흐 림'} 관찰자 2: Weather {description = '태풍'}
자, 안 드 로 이 드 에서 의 응용 을 살 펴 보 겠 습 니 다. 가장 간단 한 것 부터 Button 의 클릭 이벤트 입 니 다.
Button btn=new Button(this);  
btn.setOnClickListener(new View.OnClickListener() {  
    @Override  
    public void onClick(View v) {  
        Log.e("TAG","click");  
    }  
});  엄격 한 의미 에서 볼 때 이것 은 하나의 반전 이 라 고 할 수 있 지만 우 리 는 이 를 일대일 관찰자 모델 로 볼 수 있다. 사실은 set 시리즈 의 감청 사건 을 설정 하 는 방법 은 대부분이 반전 이 라 고 할 수 있 지만 일부 감청 기 는 add 를 통 해 추 가 된 것 이다. 이런 것들 은 관찰자 모델 이다. 예 를 들 어 RecyclerView 의 add Scroll Listener 방법 이다.
private List mScrollListeners;  
public void addOnScrollListener(OnScrollListener listener) {  
    if (mScrollListeners == null) {  
        mScrollListeners = new ArrayList();  
    }  
    mScrollListeners.add(listener);  
}  
public void removeOnScrollListener(OnScrollListener listener) {  
    if (mScrollListeners != null) {  
        mScrollListeners.remove(listener);  
    }  
}  
public void clearOnScrollListeners() {  
    if (mScrollListeners != null) {  
        mScrollListeners.clear();  
    }  
}    그리고 스크롤 이벤트 가 있 을 때 관찰자 의 방법 을 터치 하여 리 셋 합 니 다.
public abstract static class OnScrollListener {  
    public void onScrollStateChanged(RecyclerView recyclerView, int newState){}  
    public void onScrolled(RecyclerView recyclerView, int dx, int dy){}  
}  
void dispatchOnScrolled(int hresult, int vresult) {  
    //...  
    if (mScrollListeners != null) {  
        for (int i = mScrollListeners.size() - 1; i >= 0; i--) {  
            mScrollListeners.get(i).onScrolled(this, hresult, vresult);  
        }  
    }  
}  
void dispatchOnScrollStateChanged(int state) {  
    //...  
    if (mScrollListeners != null) {  
        for (int i = mScrollListeners.size() - 1; i >= 0; i--) {  
            mScrollListeners.get(i).onScrollStateChanged(this, state);  
        }  
    }  
}  또한 방송 메커니즘 은 본질 적 으로 관찰자 모드 에서 registerReceiver 방법 으로 방송 을 등록 하고 unregisterReceiver 방법 으로 등록 을 취소 한 다음 에 sendbBroadcast 로 방송 을 보 내 고 그 후에 등 록 된 방송 은 해당 하 는 방송 정 보 를 받는다. 이것 이 바로 전형 적 인 관찰자 모드 이다.
오픈 소스 프레임 워 크 EventBus 도 관찰자 모드 를 바탕 으로
관찰자 모드 의 등록, 취소, 사건 발송 세 가지 전형 적 인 방법 이 모두 있다.
EventBus.getDefault().register(Object subscriber);  
EventBus.getDefault().unregister(Object subscriber);  
EventBus.getDefault().post(Object event);  무 거 운 라 이브 러 리 RxJava 를 비교 하여 피 관찰 자 를 만 듭 니 다.
Observable myObservable = Observable.create(    
    new Observable.OnSubscribe() {    
        @Override    
        public void call(Subscriber super String> sub) {    
            sub.onNext("Hello, world!");    
            sub.onCompleted();    
        }    
    }    
);    구독 자
Subscriber mySubscriber = new Subscriber() {    
    @Override    
    public void onNext(String s) { System.out.println(s); }    
    @Override    
    public void onCompleted() { }    
    @Override    
    public void onError(Throwable e) { }    
};  
  관찰자 가 이벤트 구독 을 진행 합 니 다.
myObservable.subscribe(mySubscriber);  이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.