안 드 로 이 드 디자인 모델 학습 의 관찰자 모델
개술
관찰자 모델 은 게시/구독 모델 이 라 고도 부 르 는데 관찰자 모델 은 한 쌍 의 다 중 의존 관 계 를 정의 하여 여러 관찰자 대상 이 특정한 주제 대상 을 동시에 감청 하도록 한다.이 테마 대상 은 상태 가 변 할 때 모든 관찰자 대상 에 게 자동 으로 자신 을 업데이트 할 수 있 도록 알려 줍 니 다.
패턴 속 캐릭터
추상 적 인 주제(Subject):모든 관찰자 대상 의 인용 을 하나의 집합 에 저장 하고 모든 주제 에 모든 수량의 관찰자 가 있 을 수 있 습 니 다.추상 적 인 테 마 는 관찰자 대상 을 추가 하고 삭제 할 수 있 는 인 터 페 이 스 를 제공 합 니 다.
구체 적 인 주제(Concrete Subject):관련 상 태 를 구체 적 인 관찰자 대상 에 저장 합 니 다.구체 적 인 주제 내부 상태 가 바 뀌 었 을 때 등 록 된 모든 관찰자 에 게 알림 을 보 냅 니 다.
추상 관찰자(Observer):모든 구체 적 인 관찰자 에 게 인 터 페 이 스 를 정의 하고 테마 알림 을 받 을 때 자신 을 업데이트 합 니 다.
구체 적 인 관찰자(ConcreteObserver):추상 적 인 관찰자 역할 이 요구 하 는 업데이트 인 터 페 이 스 를 실현 하여 자신의 상태 와 주제 상 태 를 조 화 롭 게 한다.
1.Subject 와 Observer 는 한 쌍 이상 의 관계 이다.즉,관찰 자 는 Observer 인 터 페 이 스 를 실현 하고 자신 을 Subject 에 등록 하면 메시지 이 벤트 를 받 을 수 있다.
2.자바 API 는 내 장 된 관찰자 모드 클래스 가 있 습 니 다.자바 util.Observable 클래스 와 자바 util.Observer 인터페이스 입 니 다.이것 은 각각 Subject 와 Observer 의 역할 에 대응 합 니 다.
3.자바 API 를 사용 하 는 관찰자 모드 클래스 입 니 다.주의해 야 할 것 은 피 관찰자 가 notify Observer()함수 로 관찰자 에 게 알 리 기 전에 setChanged()함 수 를 호출 해 야 합 니 다.그렇지 않 으 면 관찰자 가 통 지 를 받 을 수 없습니다.
4.자바 API 를 사용 하 는 단점 도 뚜렷 합 니 다.Observable 은 하나의 클래스 이기 때문에 자바 가 단일 계승 만 허용 하 는 단점 으로 인해 다른 부모 클래스 의 속성 을 동시에 얻 으 려 면 어댑터 모드 나 내부 클래스 만 선택 할 수 있 습 니 다.또한 setChanged()함수 가 proctected 속성 이기 때문에 Observable 클래스 를 계승 하지 않 는 한,그렇지 않 으 면 이런 속성 을 사용 할 수 없다.이것 은 디자인 모델 의 원칙 에 위배 된다.조합 을 많이 사용 하고 계승 을 적 게 사용 하 는 것 이다.
관찰자 모드 예시
MyPerson 은 피 관찰자
public class MyPerson extends Observable {
private String name;
private int age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
setChanged();
notifyObservers();
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
setChanged();
notifyObservers();
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
setChanged();
notifyObservers();
}
@Override
public String toString() {
return "MyPerson [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}
setChanged();데이터 변경 을 알 리 고 notifyObserver()를 통 해 알 립 니 다.관찰자 에 게 신 호 를 보내다.MyObserver 는 관찰자 입 니 다.
public class MyObserver implements Observer {
private int id;
private MyPerson myPerson;
public MyObserver(int id) {
System.out.println(" ---->" + id);
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public MyPerson getMyPerson() {
return myPerson;
}
public void setMyPerson(MyPerson myPerson) {
this.myPerson = myPerson;
}
@Override
public void update(Observable observable, Object data) {
System.out.println(" ---->" + id + " ");
this.myPerson = (MyPerson) observable;
System.out.println(((MyPerson) observable).toString());
}
}
관찰자 가 알림 을 받 은 후 update 방법 으로 업데이트 작업 을 진행 합 니 다.
public class MainActivity extends Activity {
private Button btnAddObserver;
private Button btnChangeData;
private MyPerson observable;
private MyObserver myObserver;
private List<MyObserver> myObservers;
private ListView listview;
private int i;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
MyListAdapter myListAdapter = new MyListAdapter(MainActivity.this,
myObservers);
listview.setAdapter(myListAdapter);
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnAddObserver = (Button) findViewById(R.id.btn_add_observer);
btnChangeData = (Button) findViewById(R.id.btn_change_data);
listview = getListView();
observable = new MyPerson();
myObservers = new ArrayList<MyObserver>();
btnAddObserver.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
myObserver = new MyObserver(i);
i++;
observable.addObserver(myObserver);
myObservers.add(myObserver);
handler.sendEmptyMessage(0);
}
});
btnChangeData.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
observable.setName("a" + i);
observable.setAge(10 + i);
observable.setSex(" " + i);
handler.sendEmptyMessage(0);
}
});
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
observable.deleteObserver(myObserver);
}
}
Android 소스 코드 의 모드 구현예전 에 우리 가 가장 자주 사용 하 는 컨트롤 은 ListView 였 는데 ListView 의 가장 중요 한 점 은 Adapter 였 다.우리 가 ListView 에 데 이 터 를 추가 한 후에 우 리 는 모두 하나의 방법 을 호출 했다.notifyDataSetChanged().이 방법 은 바로 우리 가 말 한 관찰자 모드 를 사용 한 것 이다.
이 방법 을 따라 notifyDataSetChanged 방법 입 니 다.이 방법 은 BaseAdapter 에 정의 되 어 있 습 니 다.코드 는 다음 과 같 습 니 다.
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
//
private final DataSetObservable mDataSetObservable = new DataSetObservable();
//
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
}
데이터 가 변 할 때 notifyDataSetChanged 에서 mDataSetObservable.notifyChanged()방법 을 호출 하 는 것 을 발견 할 수 있 습 니 다.
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* Invokes onChanged on each observer. Called when the data set being observed has
* changed, and which when read contains the new state of the data.
*/
public void notifyChanged() {
synchronized(mObservers) {
// onChanged
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
}
mDataSetObservable.notifyChanged()에서 모든 관찰 자 를 옮 겨 다 니 며 onChanged 방법 을 호출 합 니 다.그렇다면 이 관찰자 들 은 어디에서 왔 을 까?우선 ListView 는 setAdapter 방법 으로 Adapter 를 설정 합 니 다.
@Override
public void setAdapter(ListAdapter adapter) {
// adapter, Adapter
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
//
super.setAdapter(adapter);
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
//
mItemCount = mAdapter.getCount();
checkFocus();
// :
mDataSetObserver = new AdapterDataSetObserver();
// Adapter , DataSetObservable
mAdapter.registerDataSetObserver(mDataSetObserver);
//
} else {
//
}
requestLayout();
}
Adapter 를 설정 할 때 Adapter DataSetObserver 를 구축 하고 마지막 으로 이 관찰 자 를 adapter 에 등록 합 니 다.그러면 우리 의 피 관찰자,관찰자 가 모두 있 습 니 다.AdapterDataSetObserver 는 ListView 의 부모 클래스 AbsListView 에 정 의 됩 니 다.코드 는 다음 과 같 습 니 다.
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
@Override
public void onChanged() {
super.onChanged();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
@Override
public void onInvalidated() {
super.onInvalidated();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
}
AbsListView 의 부모 클래스 AdapterView 를 계승 한 AdapterDataSetObserver 입 니 다.코드 는 다음 과 같 습 니 다.
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
// Adapter notifyDataSetChanged onChanged ,
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
// Adapter
mItemCount = getAdapter().getCount();
// Detect the case where a cursor that was previously invalidated has
// been repopulated with new data.
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
// ListView、GridView AdapterView
requestLayout();
}
//
public void clearSavedState() {
mInstanceState = null;
}
}
ListView 의 데이터 가 변 할 때 Adapter 의 notifyDataSetChanged 함 수 를 호출 합 니 다.이 함 수 는 DataSetObservable 의 notifyChanged 함 수 를 호출 합 니 다.이 함 수 는 모든 관찰자(AdapterDataSetObserver)의 onChanged 방법 을 호출 합 니 다.이것 이 바로 관찰자 모드 다!요약:AdapterView 에는 내부 클래스 AdapterDataSetObserver 가 있 습 니 다.ListView 에서 Adapter 를 설정 할 때 AdapterDataSetObserver 를 구축 하고 Adapter 에 등록 합 니 다.이것 이 바로 관찰자 입 니 다.한편,Adapter 에는 관찰 가능 한 데이터 세트 DataSetObservable 이 포함 되 어 있 습 니 다.데이터 수량 이 변경 되 었 을 때 개발 자 는 AdapternotifyDataSetChanged 를 수 동 으로 호출 하고 notifyDataSetChanged 는 실제 적 으로 DataSetObservable 의 notify Changed 함 수 를 호출 합 니 다.이 함 수 는 모든 관찰자 의 onChanged 함 수 를 옮 겨 다 닙 니 다.AdapterDataSetObserver 의 onChanged 함수 에서 Adapter 의 데이터 세트 의 새로운 수량 을 가 져 온 다음 ListView 의 requestLayout()방법 으로 레이아웃 을 다시 하고 사용자 인터페이스 를 업데이트 합 니 다.
비교적 유명한 사용 관찰자 모델 의 오픈 소스 프레임 워 크 는
장점.
관찰자 모델 은 주제 와 구체 적 인 관찰자 의 결합 을 해제 하고 결합 하 는 쌍방 이 구체 적 인 것 에 의존 하 는 것 이 아니 라 추상 에 의존 하도록 한다.그래서 각자 의 변 화 는 다른 쪽 의 변화 에 영향 을 주지 않 는 다.
결점.
의존 관 계 는 완전히 해제 되 지 않 았 고 추상 적 인 통지 자 는 추상 적 인 관찰자 에 게 의존 했다.
적용 필드
한 대상 의 변화 가 다른 대상 으로 바 뀌 어야 할 때,구체 적 으로 몇 개의 대상 이 바 뀌 어야 할 지 모른다.
하나의 추상 적 인 특정한 유형 은 두 가지 측면 이 있 는데 그 중의 한 가지 측면 이 다른 측면 에 의존 할 때 관찰자 모델 로 이 두 가 지 를 독립 된 대상 에 포장 하여 각자 독립 적 으로 변화 시 키 고 재 활용 할 수 있다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.