java设计模式
1.六大原则
1.1单一职责原则
1.2接口隔离原则
1.3依赖倒转原则
1.4里氏替换原则
1.5开闭原则 ocp
1.6迪米特法则
2.设计模式类型分类
2.1 创建型模式5种:
单例模式,工厂模式,抽象工厂模式,原型模式,建造者模式
2.2 结构型模式七种:
适配器模式,桥接模式,装饰模式,组合模式,外观模式/门面模式,享元模式,代理模式
2.3 行为型模式11种:
模板方法模式,命令模式,访问者模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式(Interpreter模式),状态模式,策略模式,职责链模式(责任链模式)
3.创建型模式
3.1单例模式 Singleton Pattern
**意图:**保证一个类仅有一个实例,并提供一个访问它的全局访问点。
**主要解决:**一个全局使用的类频繁地创建与销毁。
**何时使用:**当您想控制实例数目,节省系统资源的时候。
**如何解决:**判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
**关键代码:**构造函数是私有的。
3.1.1 饿汉式
//1.饿汉式-静态变量初始化时实例化对象
class HungryStaticProperty {
//1. 构造器私有化, 外部不能new
private HungryStaticProperty() {
}
//2.本类内部创建对象实例
private final static HungryStaticProperty instance = new HungryStaticProperty();
//3. 提供一个公有的静态方法,返回实例对象
public static HungryStaticProperty getInstance() {
return instance;
}
}
//2.饿汉式-静态变量-静态代码块里实例化
class HungryStaticCodeBlock {
//1. 构造器私有化, 外部能new
private HungryStaticCodeBlock() {
}
//2.本类内部创建对象实例
private static HungryStaticCodeBlock instance;
static {
instance = new HungryStaticCodeBlock();
}
//3. 提供一个公有的静态方法,返回实例对象
public static HungryStaticCodeBlock getInstance() {
return instance;
}
}
3.1.2 懒汉式
//3.懒汉式-synchronized同步创建方法,缺点是每一次getInstance()都要同步,效率低
class LazySynchronized {
private static LazySynchronized instance;
private LazySynchronized() {}
//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
//即懒汉式
public static synchronized LazySynchronized getInstance() throws InterruptedException {
if(instance == null) {
instance = new LazySynchronized();
}
return instance;
}
}
//4.懒汉式-双重检查,解决每次都要synchronized的问题,重点volatile,线程可见性。
class LazyDoubleCheck {
private static volatile LazyDoubleCheck instance;
private LazyDoubleCheck() {}
//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
//即懒汉式
public static LazyDoubleCheck getInstance() throws InterruptedException {
if(instance == null) {
synchronized (LazyDoubleCheck.class) {
if(instance == null) {
instance = new LazyDoubleCheck();
}
}
}
return instance;
}
}
//5.静态内部类完成, 推荐使用-
class StaticInnerClasses {
private static volatile StaticInnerClasses instance;
static {
System.out.println("外部类加载");
}
//构造器私有化
private StaticInnerClasses() {}
//写一个静态内部类,该类中有一个静态属性 Singleton
private static class SingletonInstance {
static {
System.out.println("静态内部类加载");
}
//类加载时初始化,而且由类加载器保证初始化一次。
private static final StaticInnerClasses INSTANCE = new StaticInnerClasses();
}
//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
public static StaticInnerClasses getInstance() {
return SingletonInstance.INSTANCE;
}
}
3.1.3 枚举实现单例
//6.使用枚举,可以实现单例, 推荐
enum EnumSingleton {
INSTANCE; //属性
public void sayOK() {
System.out.println("ok~");
}
}
3.1.4 kotlin里实现单例
object KotlinSingleton {
fun helloWorld() {
println("Hello world")
}
}
class KotlinLazySingleton private constructor(var age: Int) {
init {
println("KotlinLazySingleton")
}
companion object {
val instance: KotlinLazySingleton by lazy {
println("KotlinLazySingleton by lazy")
KotlinLazySingleton(10)
}
}
}
//构造函数带参的单例
class SingletonSecond private constructor(var age: Int = 0) {
fun getLastAge() = age
init {
println("SingletonSecond init")
}
companion object {
@Volatile
private var INSTANCE: SingletonSecond? = null
fun getInstance(): SingletonSecond {
return INSTANCE ?: synchronized(this) {
val instance = SingletonSecond(18)
INSTANCE = instance
instance
}
}
}
}
3.1.4 android sdk里的单例模式
getSystemService
的实现是一个单例模式
val s1 = getSystemService(Context.ACTIVITY_SERVICE)
val s2 = getSystemService(Context.ACTIVITY_SERVICE)
val s3 = getSystemService(Context.ACTIVITY_SERVICE)
跟踪代码,会发现最后是在一个静态代码块里配置好如何创建一个实例并缓存,属于懒加载。
package android.app;
final class SystemServiceRegistry {
private static final String TAG = "SystemServiceRegistry";
// Service registry information.
// This information is never changed once static initialization has completed.
private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
new HashMap<Class<?>, String>();
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
private static int sServiceCacheSize;
// Not instantiable.
private SystemServiceRegistry() { }
static {
registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
new CachedServiceFetcher<AccessibilityManager>() {
@Override
public AccessibilityManager createService(ContextImpl ctx) {
return AccessibilityManager.getInstance(ctx);
}});
registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
new CachedServiceFetcher<CaptioningManager>() {
@Override
public CaptioningManager createService(ContextImpl ctx) {
return new CaptioningManager(ctx);
}});
...略
}
private static <T> void registerService(String serviceName, Class<T> serviceClass,
ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
/**
* Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
}
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
private final int mCacheIndex;
CachedServiceFetcher() {
// Note this class must be instantiated only by the static initializer of the
// outer class (SystemServiceRegistry), which already does the synchronization,
// so bare access to sServiceCacheSize is okay here.
mCacheIndex = sServiceCacheSize++;
}
@Override
@SuppressWarnings("unchecked")
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
final int[] gates = ctx.mServiceInitializationStateArray;
for (;;) {
boolean doInitialize = false;
synchronized (cache) {
// Return it if we already have a cached instance.
T service = (T) cache[mCacheIndex];
if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
return service;
}
// If we get here, there's no cached instance.
// Grr... if gate is STATE_READY, then this means we initialized the service
// once but someone cleared it.
// We start over from STATE_UNINITIALIZED.
if (gates[mCacheIndex] == ContextImpl.STATE_READY) {
gates[mCacheIndex] = ContextImpl.STATE_UNINITIALIZED;
}
// It's possible for multiple threads to get here at the same time, so
// use the "gate" to make sure only the first thread will call createService().
// At this point, the gate must be either UNINITIALIZED or INITIALIZING.
if (gates[mCacheIndex] == ContextImpl.STATE_UNINITIALIZED) {
doInitialize = true;
gates[mCacheIndex] = ContextImpl.STATE_INITIALIZING;
}
}
if (doInitialize) {
// Only the first thread gets here.
T service = null;
@ServiceInitializationState int newState = ContextImpl.STATE_NOT_FOUND;
try {
// This thread is the first one to get here. Instantiate the service
// *without* the cache lock held.
service = createService(ctx);
newState = ContextImpl.STATE_READY;
} catch (ServiceNotFoundException e) {
onServiceNotFound(e);
} finally {
synchronized (cache) {
cache[mCacheIndex] = service;
gates[mCacheIndex] = newState;
cache.notifyAll();
}
}
return service;
}
// The other threads will wait for the first thread to call notifyAll(),
// and go back to the top and retry.
synchronized (cache) {
while (gates[mCacheIndex] < ContextImpl.STATE_READY) {
try {
cache.wait();
} catch (InterruptedException e) {
Log.w(TAG, "getService() interrupted");
Thread.currentThread().interrupt();
return null;
}
}
}
}
}
public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
}
3.2 简单工厂/工厂方法/抽象工厂 Factory Pattern
3.2.1 工厂方法
**意图:**定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
**主要解决:**主要解决接口选择的问题。
**何时使用:**我们明确地计划不同条件下创建不同实例时。
**如何解决:**让其子类实现工厂接口,返回的也是一个抽象的产品。
3.2.2 抽象工厂模式
**意图:**提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
**主要解决:**主要解决接口选择的问题。
**何时使用:**系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
**如何解决:**在一个产品族里面,定义多个产品。
**关键代码:**在一个工厂里聚合多个同类产品。
在实际使用中,工厂模式一般都会跟反射一起使用。
public interface Car {
public void run();
}
//宝马汽车
public class BMCar implements Car{
@Override
public void run() {
System.out.println("宝马汽车疾驰中......");
}
}
//奔驰汽车
public class BCCar implements Car {
@Override
public void run() {
System.out.println("奔驰汽车飞驰中...");
}
}
//山寨汽车
public class UnknownCar implements Car {
@Override
public void run() {
System.out.println("山寨汽车飞驰中...");
}
}
3.2.3 简单工厂
public class CarFactory {
public static Car productCar(String brand) throws Exception{
if(brand.equals("BM")){
System.out.println("汽车工厂生产宝马汽车...");
return new BMCar();
}else if(brand.equals("BC")){
System.out.println("汽车工厂生产奔驰汽车...");
return new BCCar();
}else{
throw new UnknownCar();
}
}
}
public class Client {
public static void main(String[] args) {
try
{
Car car;
String brand = Auto.getBrandName();
car = CarFactory.productCar(brand);
car.run();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
3.2.4 简单工厂类图
classDiagram
AbstractProduct <|-- ConcreteProductA
AbstractProduct <|-- ConcreteProductB
AbstractProduct <|-- UnknownProduct
SimpleFactory ..> AbstractProduct
Client ..> SimpleFactory
Client ..> AbstractProduct
3.2.5 工厂方法
//汽车工厂接口,只有一个生产汽车的方法
public interface CarFactory {
public Car produceCar();
}
public class BMFactory implements CarFactory {
public Car produceCar() {
System.out.println("宝马工厂生产宝马汽车中...");
return new BMCar();
}
}
public class BCFactory implements CarFactory{
@Override
public Car produceCar() {
System.out.println("奔驰汽车厂生产汽车..");
return new BCCar();
}
}
public class Client {
public static void main(String[] args) {
Car car;
CarFactory carFactory;
//根据条件,创建工厂,然后工厂生产汽车。//这里面一般会用到反射?
carFactory = (CarFactory)XMLUtil.getBean();
car = carFactory.produceCar();
car.run();
}
}
3.2.6 工厂方法类图
classDiagram
AbstractProduct <|-- ConcreteProductA
AbstractProduct <|-- ConcreteProductB
AbstractProduct <|-- ConcreteProductC
AbstractProduct <|-- UnknownProduct
AbstractFactory <|-- ConcreteFactoryA
AbstractFactory <|-- ConcreteFactoryB
AbstractFactory <|-- ConcreteFactoryC
ConcreteFactoryA ..> ConcreteProductA
ConcreteFactoryB ..> ConcreteProductB
ConcreteFactoryC ..> ConcreteProductC
AbstractFactory ..> AbstractProduct
Client ..> AbstractFactory
Client ..> AbstractProduct
3.2.7 抽象工厂
如果汽车细分大巴,公交车,的士,按品牌再细分一下,宝马大巴/宝马公交车/宝马的士,奔驰大巴/奔驰公交车/奔驰的士,如果用工厂方法来做,工厂类会很多,所以有了抽象工厂,一个工厂一次可以生产多个相同品牌的产品(产品族)
public interface Factory {
public Bus produceBus();
public Car produceCar();
}
public class BMFactory implements Factory{
@Override
public Bus produceBus() {
System.out.println("宝马汽车厂生产宝马大巴...");
return new BMBus();
}
@Override
public Car produceCar() {
System.out.println("宝马汽车厂生产宝马轿车...");
return new BMCar();
}
}
public class BCFactory implements Factory{
@Override
public Bus produceBus() {
System.out.println("奔驰汽车厂生产奔驰大巴...");
return null;
}
@Override
public Car produceCar() {
System.out.println("奔驰汽车厂生产奔驰轿车...");
return null;
}
}
public class Client {
public static void main(String[] args) {
Bus bus;
Car car;
Factory factory = (Factory)XMLUtil.getBean();
bus = factory.produceBus();
bus.pull();
car = factory.produceCar();
car.run();
}
}
3.2.8 抽象工厂类图
classDiagram
AbstractProductA <|-- ConcreteProductA1
AbstractProductA <|-- ConcreteProductA2
AbstractProductA <|-- ConcreteProductA3
AbstractProductB <|-- ConcreteProductB1
AbstractProductB <|-- ConcreteProductB2
AbstractProductB <|-- ConcreteProductB3
AbstracFactory <|-- ConcreteFactoryA
AbstracFactory <|-- ConcreteFactoryB
Client ..> AbstracFactory
AbstracFactory ..> AbstractProductA
AbstracFactory ..> AbstractProductB
ConcreteFactoryA ..> AbstractProductA
ConcreteFactoryB ..> AbstractProductB
class AbstracFactory {
+createAbstractProductA() AbstractProductA
+createAbstractProductB() AbstractProductB
}
3.3原型模式 Prototype Pattern
为了拷贝现有对象。直接new
的对象,属性还需要一个一个的设置,十分麻烦,直接克隆(new+setting)一个对象,产生一个新的对象并且和被克隆对象有相同的属性。
3.3.1 Cloneable接口与Object
java 里的Object
对象有一个clone
方法(注意这一个方法返回的是Object),但是如果想实现克隆效果,自定义的类还需要实现Cloneable
接口
/**
* Class {@code Object} is the root of the class hierarchy.
* Every class has {@code Object} as a superclass. All objects,
* including arrays, implement the methods of this class.
*
* @author unascribed
* @see java.lang.Class
* @since 1.0
*/
public class Object {
...
/**
* Creates and returns a copy of this object. The precise meaning
* of "copy" may depend on the class of the object. The general
* intent is that, for any object {@code x}, the expression:
* <blockquote>
* <pre>
* x.clone() != x</pre></blockquote>
* will be true, and that the expression:
* <blockquote>
* <pre>
* x.clone().getClass() == x.getClass()</pre></blockquote>
* will be {@code true}, but these are not absolute requirements.
* While it is typically the case that:
* <blockquote>
* <pre>
* x.clone().equals(x)</pre></blockquote>
* will be {@code true}, this is not an absolute requirement.
* <p>
* By convention, the returned object should be obtained by calling
* {@code super.clone}. If a class and all of its superclasses (except
* {@code Object}) obey this convention, it will be the case that
* {@code x.clone().getClass() == x.getClass()}.
* <p>
* By convention, the object returned by this method should be independent
* of this object (which is being cloned). To achieve this independence,
* it may be necessary to modify one or more fields of the object returned
* by {@code super.clone} before returning it. Typically, this means
* copying any mutable objects that comprise the internal "deep structure"
* of the object being cloned and replacing the references to these
* objects with references to the copies. If a class contains only
* primitive fields or references to immutable objects, then it is usually
* the case that no fields in the object returned by {@code super.clone}
* need to be modified.
* <p>
* The method {@code clone} for class {@code Object} performs a
* specific cloning operation. First, if the class of this object does
* not implement the interface {@code Cloneable}, then a
* {@code CloneNotSupportedException} is thrown. Note that all arrays
* are considered to implement the interface {@code Cloneable} and that
* the return type of the {@code clone} method of an array type {@code T[]}
* is {@code T[]} where T is any reference or primitive type.
* Otherwise, this method creates a new instance of the class of this
* object and initializes all its fields with exactly the contents of
* the corresponding fields of this object, as if by assignment; the
* contents of the fields are not themselves cloned. Thus, this method
* performs a "shallow copy" of this object, not a "deep copy" operation.
* <p>
* The class {@code Object} does not itself implement the interface
* {@code Cloneable}, so calling the {@code clone} method on an object
* whose class is {@code Object} will result in throwing an
* exception at run time.
*
* @return a clone of this instance.
* @throws CloneNotSupportedException if the object's class does not
* support the {@code Cloneable} interface. Subclasses
* that override the {@code clone} method can also
* throw this exception to indicate that an instance cannot
* be cloned.
* @see java.lang.Cloneable
*/
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
...
}
java里的原型模式,必段实现 Cloneable
接口。
public interface Cloneable {
}
3.3.2代码示例
public abstract class Shape implements Cloneable {
private String id;
protected String type;
abstract void draw();
public String getType(){
return type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
public class Rectangle extends Shape {
public Rectangle(){
type = "Rectangle";
}
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Client {
public static void main(String[] args) {
System.out.println("原型模式完成对象的创建");
Rectangle rectangle = Rectangle();
rectangle.setId("101010101");
Rectangle rectangle2 = rectangle.clone();
}
}
3.3.3 UML图
classDiagram
Prototype <|-- ConcretePrototypeA
Prototype <|-- ConcretePrototypeB
Cloneable <|-- Prototype
Client ..> Prototype
Client ..> newPrototype : 参过克隆创建了一个新的对象并且设置好了相应属性
class Prototype {
+clone() Prototype
}
class ConcretePrototypeA {
+clone() Prototype
}
class ConcretePrototypeB {
+clone() Prototype
}
class Cloneable {
+clone() Object
}
<<interface>> Cloneable
3.4.3 深拷贝与浅拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
深复制方案:
1.自定义的成员属性都要实现cloneable接口,
2.ObjectOutputStream
和 ObjectInputStream
和序列化,例如toJson
和fromJson
3.4.4安卓sdk中 Cloneable的子类
package android.os;
public final class Bundle extends BaseBundle implements Cloneable, Parcelable {}
package android.animation;
public abstract class Animator implements Cloneable {}
package android.util;
public class SparseLongArray implements Cloneable {}
package android.util;
public class SparseArray<E> implements Cloneable {}
package java.util;
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {}
package android.content;
public class Intent implements Parcelable, Cloneable {}
package java.util;
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{}
省略省略
3.4 建造者模式 Builder Pattern
**意图:**将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
**主要解决:**主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
Builder里的方法一般是返回this,然后可以链式调用。
3.4.1 类图
classDiagram
AbstractBuilder <|-- ConcreteBuilder
Director ..> AbstractBuilder
Director ..> Product
class AbstractBuilder {
+setPropertyA() AbstractBuilder
+setPropertyB() AbstractBuilder
+setPropertyC() AbstractBuilder
+setPropertyD() AbstractBuilder
+build() Product
}
建造者模式的四个角色
1) Product(产品角色): 一个具体的产品对象。
2) Builder(抽象建造者):创建一个Product对象的各个部件指定的 接口/抽象类。
3) ConcreteBuilder(具体建造者): 实现接口,构建和装配各个部件。
4) Director(指挥者): 构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,
一是:隔离了客户与对象的生产过程,
二是:负责控制产品对象的生产过程。
以安卓sdk里的源码为例
GestureDescription与Builder
classDiagram
direction BT
class Builder {
+ Builder()
- List~StrokeDescription~ mStrokes
- int mDisplayId
+ addStroke(StrokeDescription) Builder
+ setDisplayId(int) Builder
+ build() GestureDescription
}
public final class GestureDescription {
...
private GestureDescription() {
this(new ArrayList<>());
}
private GestureDescription(List<StrokeDescription> strokes) {
this(strokes, Display.DEFAULT_DISPLAY);
}
private GestureDescription(List<StrokeDescription> strokes, int displayId) {
mStrokes.addAll(strokes);
mDisplayId = displayId;
}
......
/**
* Builder for a {@code GestureDescription}
*/
public static class Builder {
private final List<StrokeDescription> mStrokes = new ArrayList<>();
private int mDisplayId = Display.DEFAULT_DISPLAY;
/**
* Adds a stroke to the gesture description. Up to
* {@link GestureDescription#getMaxStrokeCount()} paths may be
* added to a gesture, and the total gesture duration (earliest path start time to latest
* path end time) may not exceed {@link GestureDescription#getMaxGestureDuration()}.
*
* @param strokeDescription the stroke to add.
*
* @return this
*/
public Builder addStroke(@NonNull StrokeDescription strokeDescription) {
if (mStrokes.size() >= MAX_STROKE_COUNT) {
throw new IllegalStateException(
"Attempting to add too many strokes to a gesture. Maximum is "
+ MAX_STROKE_COUNT
+ ", got "
+ mStrokes.size());
}
mStrokes.add(strokeDescription);
if (getTotalDuration(mStrokes) > MAX_GESTURE_DURATION_MS) {
mStrokes.remove(strokeDescription);
throw new IllegalStateException(
"Gesture would exceed maximum duration with new stroke");
}
return this;
}
/**
* Sets the id of the display to dispatch gestures.
*
* @param displayId The logical display id
*
* @return this
*/
public @NonNull Builder setDisplayId(int displayId) {
mDisplayId = displayId;
return this;
}
public GestureDescription build() {
if (mStrokes.size() == 0) {
throw new IllegalStateException("Gestures must have at least one stroke");
}
return new GestureDescription(mStrokes, mDisplayId);
}
}
}
AlertDialog.Builder
classDiagram
direction BT
class Builder {
+ Builder(Context)
+ Builder(Context, int)
+ setIcon(Drawable) Builder
+ setTitle(int) Builder
+ setOnItemSelectedListener(OnItemSelectedListener) Builder
+ setSingleChoiceItems(CharSequence[], int, OnClickListener) Builder
+ setView(View) Builder
+ setNeutralButton(int, OnClickListener) Builder
+ setNegativeButton(int, OnClickListener) Builder
+ setSingleChoiceItems(ListAdapter, int, OnClickListener) Builder
+ setItems(int, OnClickListener) Builder
+ setIcon(int) Builder
+ setView(int) Builder
+ setSingleChoiceItems(Cursor, int, String, OnClickListener) Builder
+ setPositiveButton(CharSequence, OnClickListener) Builder
+ setInverseBackgroundForced(boolean) Builder
+ setPositiveButton(int, OnClickListener) Builder
+ setOnCancelListener(OnCancelListener) Builder
+ setCursor(Cursor, OnClickListener, String) Builder
+ setMultiChoiceItems(Cursor, String, String, OnMultiChoiceClickListener) Builder
+ setNeutralButton(CharSequence, OnClickListener) Builder
+ setTitle(CharSequence) Builder
+ setCancelable(boolean) Builder
+ setOnDismissListener(OnDismissListener) Builder
+ setIconAttribute(int) Builder
+ getContext() Context
+ setOnKeyListener(OnKeyListener) Builder
+ setMessage(CharSequence) Builder
+ setMultiChoiceItems(int, boolean[], OnMultiChoiceClickListener) Builder
+ setMessage(int) Builder
+ setCustomTitle(View) Builder
+ setAdapter(ListAdapter, OnClickListener) Builder
+ setMultiChoiceItems(CharSequence[], boolean[], OnMultiChoiceClickListener) Builder
+ setItems(CharSequence[], OnClickListener) Builder
+ setSingleChoiceItems(int, int, OnClickListener) Builder
+ setView(View, int, int, int, int) Builder
+ show() AlertDialog
+ setRecycleOnMeasureEnabled(boolean) Builder
+ create() AlertDialog
+ setNegativeButton(CharSequence, OnClickListener) Builder
}
public class AlertDialog extends Dialog implements DialogInterface {
......
protected AlertDialog(Context context) {
this(context, 0);
}
protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
this(context, 0);
setCancelable(cancelable);
setOnCancelListener(cancelListener);
}
protected AlertDialog(Context context, @StyleRes int themeResId) {
this(context, themeResId, true);
}
AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
createContextThemeWrapper);
mWindow.alwaysReadCloseOnTouchAttr();
mAlert = AlertController.create(getContext(), this, getWindow());
}
......
public static class Builder {
public Builder(Context context) {
this(context, resolveDialogTheme(context, Resources.ID_NULL));
}
public Builder(Context context, int themeResId) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, themeResId)));
}
......
public Builder setView(View view) {
P.mView = view;
P.mViewLayoutResId = 0;
P.mViewSpacingSpecified = false;
return this;
}
public AlertDialog create() {
...
return dialog;
}
public AlertDialog show() {
final AlertDialog dialog = create();
dialog.show();
return dialog;
}
}
}