Android 와 결합 하여 Builder 모드
Builder 모드, 대상 생 성 형 디자인 모드.디자인 모델 에 대해 말하자면 약간 심오 하 다 고 느 낄 수 있 습 니 다. 사실은 그렇지 않 습 니 다. 우 리 는 매일 코드 를 쓰 는 것 이 얼마나 적은 지 다양한 디자인 모델 과 접촉 하고 있 습 니 다. 다만 눈치 채 지 못 했 을 뿐 입 니 다.여기 서 Builder 모드 를 말씀 드 리 겠 습 니 다.
Android 의 Builder 모드
Android 개발 에 서 는 언제 Builder 모드 를 사용 합 니까?사실은 간단 하 다. 컨트롤 을 사용 하고 싶 을 때 나 대상 을 사용 하고 싶 을 때 그 를 직접 새로 만 들 수 없다 는 것 이다.그렇다면 이 컨트롤 (대상) 의 실현 은 대부분 Builder 모드 를 사용 한 것 이다.
AlertDialog.Builder
private void InitView() {
//
TextView mTextView = new TextView(this);
Button mButton = new Button(this);
// Builder Dialog
AlertDialog.Builder builder=new
AlertDialog.Builder(this)
.setTitle("My Dialog")
.setMessage("This is Test Dialog")
.setIcon(R.drawable.application_icon);
AlertDialog dialog=builder.create();
}
위의 코드 와 같이, 우 리 는 일반적인 방식 (new) 에 따라 TextView 대상 과 Button 대상 을 만 들 수 있 습 니 다. 그러나 AlertDialog 차례 가 되 었 을 때, 먼저 AlertDialog. Builder 대상 을 만 든 다음, 이 Builder 대상 을 통 해 AlertDialog 의 인 스 턴 스 를 만 들 수 있 습 니 다. 마찬가지 로 모두 Android 의 컨트롤 입 니 다. 차이 가 왜 이렇게 큽 니까? (Dialog 가 복잡 하기 때 문 입 니 다! o(╯□╰)o)。
다음은 AlertDialog 의 소스 코드 를 결합 하여 간단하게 분석 할 수 있다.
protected AlertDialog(@NonNull Context context) {
this(context, 0);
}
public static class Builder {
private final AlertController.AlertParams P;
public Builder(@NonNull Context context) {
this(context, resolveDialogTheme(context, 0));
}
public Builder(@NonNull Context context, @StyleRes int themeResId) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, themeResId)));
mTheme = themeResId;
}
public Builder setTitle(@Nullable CharSequence title) {
P.mTitle = title;
return this;
}
public Builder setMessage(@Nullable CharSequence message) {
P.mMessage = message;
return this;
}
public Builder setIcon(@DrawableRes int iconId) {
P.mIconId = iconId;
return this;
}
.....
}
public AlertDialog create() {
// We can't use Dialog's 3-arg constructor with the createThemeContextWrapper param,
// so we always have to re-set the theme
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(P.mOnCancelListener);
dialog.setOnDismissListener(P.mOnDismissListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
}
return dialog;
}
OKHttp 에 대해 서 는 모두 가 낯 설 지 않다 고 믿 습 니 다. Request 대상 을 구성 할 때 Request. Builder 를 사 용 했 습 니 다. 말 그대로 Builder 모드 도 사 용 했 습 니 다.
findViewById(R.id.get).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv.setText("");
loading.setVisibility(View.VISIBLE);
OkHttpClient client = new OkHttpClient();
Request.Builder builder = new Request.Builder()
.url(BASE_URL)
.method("GET", null);
Request request = builder.build();
Call mCall = client.newCall(request);
mCall.enqueue(new MyCallback());
}
});
이상 은 OKHttp 에 대한 전형 적 인 사용 방식 입 니 다. 여기 서 Request 대상 은 직접 만 드 는 것 이 아니 라 Request. Builder 대상 을 먼저 만 든 다음 그의 build 방법 으로 최종 request 대상 을 만 듭 니 다. Request 류 의 소스 코드 를 대충 볼 수 있 습 니 다.
public final class Request {
private final HttpUrl url;
private final String method;
private final Headers headers;
private final RequestBody body;
private final Object tag;
private Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tag = builder.tag != null ? builder.tag : this;
}
// ....
public static class Builder {
private HttpUrl url;
private String method;
private Headers.Builder headers;
private RequestBody body;
private Object tag;
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
public Builder url(HttpUrl url) {
if (url == null) throw new NullPointerException("url == null");
this.url = url;
return this;
}
/**
* Sets the URL target of this request.
*
* @throws IllegalArgumentException if {@code url} is not a valid HTTP or HTTPS URL. Avoid this
* exception by calling {@link HttpUrl#parse}; it returns null for invalid URLs.
*/
public Builder url(String url) {
if (url == null) throw new NullPointerException("url == null");
// Silently replace websocket URLs with HTTP URLs.
if (url.regionMatches(true, 0, "ws:", 0, 3)) {
url = "http:" + url.substring(3);
} else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
url = "https:" + url.substring(4);
}
HttpUrl parsed = HttpUrl.parse(url);
if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
return url(parsed);
}
/**
* Sets the URL target of this request.
*
* @throws IllegalArgumentException if the scheme of {@code url} is not {@code http} or {@code
* https}.
*/
public Builder url(URL url) {
if (url == null) throw new NullPointerException("url == null");
HttpUrl parsed = HttpUrl.get(url);
if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
return url(parsed);
}
/**
* Sets the header named {@code name} to {@code value}. If this request already has any headers
* with that name, they are all replaced.
*/
public Builder header(String name, String value) {
headers.set(name, value);
return this;
}
/** Removes all headers on this builder and adds {@code headers}. */
public Builder headers(Headers headers) {
this.headers = headers.newBuilder();
return this;
}
public Builder method(String method, RequestBody body) {
if (method == null) throw new NullPointerException("method == null");
if (method.length() == 0) throw new IllegalArgumentException("method.length() == 0");
if (body != null && !HttpMethod.permitsRequestBody(method)) {
throw new IllegalArgumentException("method " + method + " must not have a request body.");
}
if (body == null && HttpMethod.requiresRequestBody(method)) {
throw new IllegalArgumentException("method " + method + " must have a request body.");
}
this.method = method;
this.body = body;
return this;
}
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
}
}
왜 Android 시스템 에서 AlertDialog 를 만 드 는 것 은 이렇게 복잡 합 니까? TextView 처럼 하나의 인 스 턴 스 를 직접 new 로 만 들 고 set 의 각종 속성 도 똑 같이 사용 할 수 있 지 않 습 니까? Request 대상 의 생 성 은 Builder 모드 를 사용 하지 않 아 도 됩 니까? 위의 여러 가지 이상 처리, 방법 집행 은 일반적인 방식 으로 도 가능 합 니 다. Builder 모드 의 가 치 는 어디 에 있 습 니까?
이런 의문 을 가지 고 Builder 모드 를 잘 이해 해 봅 시다.
빌 더 모드
정의.
복잡 한 대상 의 구축 과 그 표 시 를 분리 시 켜 같은 구축 과정 에서 서로 다른 표 시 를 만 들 수 있 습 니 다.
적용 필드
1. 같은 방법, 서로 다른 실행 순서, 서로 다른 사건 결과 발생 2. 여러 개의 부품 이나 부품 은 모두 같은 대상 에 조립 할 수 있 지만 발생 하 는 운행 결 과 는 다르다 3. 제품 류 가 매우 복잡 하거나 제품 의 호출 순서 가 다 르 면 서로 다른 역할 을 한다 4. 한 대상 이 매우 복잡 한 대상 을 초기 화해 야 한다. 이 대상 은 많은 매개 변수 가 있 고기본 값 이 있 음
이러한 개념 을 보면 추상 적일 수 있 습 니 다. 다음은 코드 를 통 해 보 겠 습 니 다. 이전 공장 방법 모델 에서 우 리 는 공장 방법 모델 로 Mobike 가 Ofo 대상 에서 생 성 된 예 를 들 었 습 니 다. 여 기 는 여전히 두 가 지 를 예 로 들 어 Builder 모델 로 어떻게 쓰 는 지 보 겠 습 니 다.
public final class Bicycle {
public static final int SHARED = 1;
public static final int PRIVATE = 0;
@IntDef({SHARED, PRIVATE})
@Retention(RetentionPolicy.SOURCE)
public @interface bicycleType {
}
protected String color;
protected String name;
protected double charge;
protected int number;
protected int type;
protected Bicycle(BicycleBuilder builder) {
this.color = builder.color;
this.name = builder.name;
this.charge = builder.chager;
this.number = builder.number;
this.type = builder.type;
}
public static class BicycleBuilder {
private String color;
private String name;
private double chager;
private int number;
private int type;
public BicycleBuilder() {
this.color = " ";
this.name = " ";
this.chager = 0;
this.number = 0;
this.type = Bicycle.PRIVATE;
}
public BicycleBuilder setColor(String color) {
this.color = color;
return this;
}
public BicycleBuilder setName(String name) {
this.name = name;
return this;
}
public BicycleBuilder setCharge(double chager) {
this.chager = chager;
return this;
}
public BicycleBuilder setNumber(int number) {
this.number = number;
return this;
}
public BicycleBuilder setType(@bicycleType int type) {
this.type = type;
return this;
}
public Bicycle build(){
return new Bicycle(this);
}
}
@Override
public String toString() {
String typeStr= type == SHARED ? " ": " ";
return "Bicycle{" +
"color='" + color + '\'' +
", name='" + name + '\'' +
", charge= " + charge +"/ "+
", number=" + number +
", type=" + typeStr +
'}';
}
}
여기 서 Bicycle 클래스 는 5 개의 고유 한 속성 을 포함 하고 있 으 며, 동시에 그 구조 방법 을 proctected 로 설정 합 니 다. Bicycle Builder 클래스 를 통 해 Bicycle 을 만 드 는 인 스 턴 스 를 실현 합 니 다. 여기 서 Bicycle Builder 의 기본 구조 방법 은 일반적인 검은색 영구 표 개인 자전 거 를 만 들 것 입 니 다. Bicycle Builder 가 제공 하 는 몇 가지 방법 을 통 해 우 리 는 서로 다른 Bicycle 인 스 턴 스 를 만 들 수 있 습 니 다.예 를 들 어 다음 과 같은 실현:
public class BuilderPatternActivity extends AppCompatActivity {
private TextView bike_result;
private Bicycle mBicycle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_builder_pattern);
bike_result = V.f(this, R.id.bike_result);
}
/**
*
* @param view
*/
public void NormalBike(View view) {
Bicycle.BicycleBuilder builder=new Bicycle.BicycleBuilder();
mBicycle=builder.build();
updateView(mBicycle);
}
/**
*
* @param view
*/
public void Mobike(View view) {
Bicycle.BicycleBuilder builder=new Bicycle.BicycleBuilder()
.setColor(" ")
.setName(" ")
.setCharge(1.0)
.setNumber(10010)
.setType(Bicycle.SHARED);
mBicycle=builder.build();
updateView(mBicycle);
}
/**
* OFO
* @param view
*/
public void Ofo(View view) {
Bicycle.BicycleBuilder builder=new Bicycle.BicycleBuilder()
.setColor(" ")
.setName("OFO ")
.setCharge(0.5)
.setNumber(40010)
.setType(Bicycle.SHARED);
mBicycle=builder.build();
updateView(mBicycle);
}
private void updateView(Bicycle mBicycle) {
bike_result.setText("");
bike_result.setText(mBicycle.toString());
}
}
Bicycle. Bicycle Builder 가 제공 하 는 일련의 set 방법 을 통 해 우 리 는 mobike 인 스 턴 스 와 of 자전거 인 스 턴 스 를 만 들 었 습 니 다.
이것 이 바로 Builder 모드 입 니 다. 장면 에서 언급 한 바 와 같이 Builder 모드 를 통 해 같은 구축 과정 에서 우 리 는 서로 다른 결 과 를 만 들 수 있 습 니 다. 일반적으로 우리 가 만 들 대상 은 매우 복잡 하고 많은 매개 변수 가 있 습 니 다. 이런 매개 변수 중 일 부 는 필수 적 입 니 다. 예 를 들 어 OKHttp 에서 Request 의 url 매개 변 수 는 기본 값 도 있 습 니 다. 한 마디 로 하면, Builder 모드, 대상 생 성 형 디자인 모델, 우리 가 대상 을 만 드 는 데 방향 을 제공 합 니 다.
마지막 으로 Builder 모드 를 사용 한 것 - RxJava. RxJava 하면 관찰자 모드 를 쉽게 떠 올 릴 수 있 습 니 다. 좋 습 니 다. RxJava 의 가장 핵심 적 인 사상 은 관찰자 모드 입 니 다. 하지만 RxJava 를 사용 하 는 과정 을 생각해 보 세 요.
ArrayList datas = new ArrayList<>();
for (int i = 0; i < 10; i++) {
datas.add("item_" + i);
}
Observable.just(datas)
.flatMap(new Func1, Observable>() {
@Override
public Observable call(ArrayList strings) {
return Observable.from(strings);
}
})
.map(new Func1() {
@Override
public Integer call(String s) {
return s.hashCode();
}
})
.subscribe(new Action1() {
@Override
public void call(Integer Integer) {
Log.e(MainActivity.class.getSimpleName(), "call---->" + Integer);
}
});
위 코드 에서 보 듯 이 subscribe 방법 이 실행 되 기 전에 다양한 조작 자 를 통 해 원시 데이터 인 Array List 는 Integer 형식의 데이터 가 되 었 습 니 다. 즉, 우리 가 조작 자 를 사용 하 는 과정 은 Builder 모델 을 구축 하 는 과정 입 니 다. 우리 가 최종 적 으로 필요 로 하 는 제품 이 생 성 될 때 까지 입 니 다. 이것 은 Builder 모델 의 정의 와 사용 장면 과 완전히 일치 합 니 다.맞았어
Builder 모드 VS 공장 방법 모드
공장 모델 은 일반적으로 하나의 제품 을 만 드 는 것 입 니 다. 이 제품 을 만 드 는 것 을 중시 합 니 다. 만 들 기만 하면 이 제품 의 구성 부분 에 관심 이 없습니다. 코드 로 볼 때 공장 모델 은 하나의 방법 입 니 다. 이 방법 으로 제품 을 생산 할 수 있 습 니 다.
건설 자 모델 도 하나의 제품 을 만 들 지만 이 제품 을 만 들 뿐만 아니 라 이 제품 의 구성 디 테 일, 구성 과정 과 도 관련 이 있다. 코드 를 보면 건설 자 모델 은 제품 을 만 들 때 이 제품 은 여러 가지 방법 이 있다. 건설 자 모델 은 이 같은 방법 이지 만 실행 순서에 따라 서로 다른 디 테 일 을 구성 하 는 제품 을 만든다.
공장 모델 은 전체 에 관심 을 가지 고 건설 자 모델 은 세부 사항 에 관심 을 가진다.
마지막.
지금 우리 가 전에 제기 한 문제 로 돌아 가면 Builder 모델 의 의 미 는 무엇 입 니까? 다 본 후에 당신 은 이미 답 을 얻 었 을 것 입 니 다. 실질 적 인 의미 가 없습니다. Builder 모델 의 사용 은 우리 의 코드 운행 속 도 를 가속 화하 지 않 습 니 다. 디자인 모델 은 전체적으로 포장, 계승, 다 형 과 관련 된 반복 적 인 사용 입 니 다. 프로 그래 밍 기술 로 우리 가 쓸 수 있 습 니 다.고 품질 코드 의 기교.
마지막 으로 다시 한 번 말씀 드 리 지만, 엄 밀 히 말 하면 본 논문 에서 논의 한 Builder 모델 은 표준 적 인 의미 의 Builder 모델 이 아 닙 니 다. 여기 서 우 리 는 Android 소스 코드 의 측면 에서 Builder 모델 을 간소화 하고 체인 호출 과 습관 을 편리 하 게 하기 위해 원래 있 던 Director 역할 을 버 렸 습 니 다. 정통 적 인 Builder 모델 에 관심 이 있 는 학생 들 은 다시 깊이 연구 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.