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에 따라 라이센스가 부여됩니다.