android源码中使用到的设计模式(创建型)

1.单例模式

1.1定义

确保某个类只有一个实例,而且自行实例化并向整个系统提供者个实例。

1.2单例的形式

  • 饿汉模式:第一次就加载,用空间换时间。
public class SingleTon {
  private static SingleTon instance = new SingleTon();
  //构造函数不对外开放
  private SingleTon() {
  }
  //通过静态方法或枚举进行调用
  public static SingleTon getInstance() {
    return instance;
  }
}
  • 懒汉模式:只有在调用的时候才进行加载,但是第一次比较慢,用时间换空间,效率不高,并且线程不安全。
public class SingleTonLH {
  private static SingleTonLH instance;
  //构造函数不对外开放
  private SingleTonLH() {
  }

  //通过静态方法或枚举进行调用
  public static synchronized SingleTonLH getInstance() {
    if(instance == null){
      instance = new SingleTonLH();
    }
    return instance;
  }
}
  • 双重加锁模式:使用volatile和synchronized进行修饰。
public class SingleTonDCL {
  private static volatile SingleTonDCL instance;
 
  //构造函数不对外开放
  private SingleTonDCL() {
  }
  //通过静态方法或枚举进行调用
  public static SingleTonDCL getInstance() {
    if(instance == null){
      synchronized (SingleTonDCL.class) {
        if (instance == null){
          instance = new SingleTonDCL();
        }
      }
    }
    return instance;
  }
}
  • 静态内部类:线程安全,并且什么时候使用什么时候调用。
public class SingleTonFinal {
 
  // 构造函数不对外开放
  private SingleTonFinal() {
  }
 
  // 通过静态方法或枚举进行调用
  public static SingleTonFinal getInstance() {
    return SingleTonHolder.sinstance;
  }
 
  //反序列化
  private Object readResolve() throws ObjectStreamException {
    return SingleTonHolder.sinstance;
  }
  
  /**
   * 静态类部类
   */
  private static class SingleTonHolder {
    private static final SingleTonFinal sinstance = new SingleTonFinal();
  }
}
  • 枚举单例:
/**
 * 枚举单例
 */
public enum SingleTonEnum {
   INSTANCE;
   public void dosamething(){
     
   }
} 
/**
 * 调用方式
 */
class SingleTon {
  private SingleTon(){
    SingleTonEnum.INSTANCE.dosamething();
  }
}

  • 容器单例:
/**
 * 容器实现单例模式
 */
public class SingleTonManger {
  private static Map objMap = new HashMap();
 
  // 构造函数不对外开放
  private SingleTonManger() {
 
  }
 
  public static void registerService(String key, Object instance) {
    if (!objMap.containsKey(key)) {
      objMap.put(key, instance);
    }
  }
 
  public static Object getService(String key) {
    return objMap.get(key);
  }
}

1.3优缺点

优点:全局一个,节约资源。在读文件方面,可以防止同时操作。
缺点:不易扩展,如果要扩展需要修改代码,违背了开闭原则。

1.4 Android源码对应模式

我们经常在Activity中通过getSystemService(String name)这个函数来获取系统服务,比如WMS,AMS,LayoutIlater等,这些服务都会在某一个时刻以容器单例的形式保存在应用中。在源码中我们知道各个服务都是保存在ContextImpl类中,在其中定义了一个SystemServiceRegistry类

final class SystemServiceRegistry {
    // 存储所有系统服务的集合
    private static final HashMap, String> SYSTEM_SERVICE_NAMES =new HashMap, String>();
    private static final HashMap> SYSTEM_SERVICE_FETCHERS =
            new HashMap>();
    
    // 一个注册服务的并添加到结合的方法
   private static  void registerService(String serviceName, Class serviceClass,
            ServiceFetcher serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }
    
    // 静态语句块, 只在类第一次被加载的时候调用, 保证了服务只被添加一次.
    static {
        // 注册了LayoutInflate服务
        registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
                new CachedServiceFetcher() {
            @Override
            public LayoutInflater createService(ContextImpl ctx) {
                return new PhoneLayoutInflater(ctx.getOuterContext());
            }});

                
       registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
                new CachedServiceFetcher() {
            @Override
            public ActivityManager createService(ContextImpl ctx) {
                return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
            }});
        /**
         *  后面省略一大坨的注册的服务代码
        **/
    }
    
    //获得服务
     public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }
    
}

2.Buider模式

2.1定义

把一个复杂的类的构建过程和它的表示进行分离

android源码中使用到的设计模式(创建型)_第1张图片
构建模式

2.2说明

  • Director:统一组装过程
  • Product:产品抽象类
  • builder:抽象的builder类,规范产品的组建
  • concreteBuilder:具体的builder类

一般实现

1,Product 建立抽象类
/**
 * @describe 用户抽象类
 */
public abstract class Product {
  protected String name;
  protected String cardID;
  protected int age;
  protected String address;
 
  //定义抽象方法
  public abstract void setCardID();
 
  public void setName(String name) {
    this.name = name;
  }
 
  public void setAge(int age) {
    this.age = age;
  }
 
  public void setAddress(String address) {
    this.address = address;
  }
 
  //显示的内容让子类去实现
  protected abstract String showProductInfo();
}
2.具体产品类
 /** 
 * @describe product具体实现类
 */
public class SysProduct extends Product {
 
  @Override
  public void setCardID() {
    //设置默认ID
    cardID="10086"; 
  }
 
  @Override
  protected String showProductInfo() {
    return "User [name =" + name + ",cardID=" + cardID + ",age=" + age
        + "," + "address=" + address + "]";
  }
 
}
3.定义抽象的buider类
/**
 * @describe 抽象构造类
 */
abstract class Builder {
  Product product;
 
  public void buildName(String name) {
    product.setName(name);
  }
 
  public void buildCardID() {
    product.setCardID();
  }
 
  public void buildAge(int age) {
    product.setAge(age);
  }
 
  public void buildAddress(String address) {
    product.setAddress(address);
  }
 
  protected abstract void creat();
 
}
4.具体的buider实现类
/**
 * @describe 具体的builder类
 */
public class AccountBuilder extends Builder {
  SysProduct sysProduct;
 
  @Override
  protected void creat() {
    sysProduct = new SysProduct();
    sysProduct.setName("嘻嘻嘻");
    sysProduct.setAge(20);
    sysProduct.setCardID();
    sysProduct.setAddress("中国");
    System.out.println("Info : " + sysProduct.showProductInfo());
  }
 
}
5.统一组装类director
/**
 * @describe 统一组装类
 */
public class Director {
  Builder mBuilder = null;
 
  public Director(Builder builder) {
    this.mBuilder = builder;
    this.mBuilder.creat();
  }
}
6.调用
/**
 * @describe 测试类
 */
public class Test {
 
  public static void main(String[] args) {
     //统一组装
     new Director(new AccountBuilder());
  }
}

使用链式,简化Director

public class ChainProduct extends Product {
 
  @Override
  public void setCardID() {
    // 设置默认ID
    cardID = "10086";
  }
 
  @Override
  protected String showProductInfo() {
    return "Info : " + "User [name =" + name + ",cardID=" + cardID + ",age=" + age
        + "," + "address=" + address + "]";
  }
 
  public static class Builder {
    ChainProduct product;
 
    public Builder() {
      product = new ChainProduct();
    }
 
    public Builder buildName(String name) {
      product.setName(name);
      return this;
    }
 
    public Builder buildAge(int age) {
      product.setAge(age);
      return this;
    }
 
    public Builder buildAddress(String address) {
      product.setAddress(address);
      return this;
    }
    public Builder buildCardID() {
      product.setCardID();
      return this;
    }
    
    public void creat() {
      System.out.println(product.showProductInfo());
    }
  }
}
 
调用方式
new ChainProduct.Builder().buildAge(20).buildAddress("中国").creat();

2.3使用场景

  1. 相同的方法,不同的执行顺序,产生不同的事件结果
  2. 多个部件或者零件,都可以配装到一个对象,但是产生的运行结果不同
  3. 当初始化一个对象特别复杂,参数多,且很多参数默认的时候

2.4 优缺点

优点:封装性良好,使用可以使客户端不必知道产品内部组成细节。建造者独立易扩展。
缺点:会产生多余的builder对象和Director对象,消耗内存

2.5 android中使用

Director这个角色经常会被忽略. 而直接使用一个Builder来进行对象的封装, 并且这个Builder通常为链式调用, 它的每个setter方法都会返回this自身, 比如我们常用的AlertDialog。

// 一个粗略的创建dialog
// 创建构建者builder角色
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(android.R.drawable.sym_def_app_icon)
      .setTitle("标题")
      .setMessage("message")
      // 设置点击等..
      .setPositiveButton("确定", null);
// 构建
AlertDialog alertDialog = builder.create();
// 显示
alertDialog.show();

AlerDialog源代码:

public class AlertDialog extends Dialog implements DialogInterface {
    // AlertController 这个对象会保存Builder对象中的各个参数
    private AlertController mAlert;
    
    // 实际上操作的是上面这个变量中的属性
    @Override
    public void setTitle(CharSequence title) {
        super.setTitle(title);
        mAlert.setTitle(title);
    }
    
    public void setMessage(CharSequence message) {
        mAlert.setMessage(message);
    }
    // 省略一坨代码如各种setter等
    // Builder以内部类的形式存在
    public static class Builder {
        // 1.存储AlertDialog的各个参数 如title,icon等
        private final AlertController.AlertParams P;
        
        // 构造函数
        public Builder(Context context) {
            this(context, resolveDialogTheme(context, 0));
        }
        // 2. 设置参数, 我们构建的Builder设置的参数就是这些方法
        public Builder setTitle(int titleId) {
            P.mTitle = P.mContext.getText(titleId);
            return this;
        }
        
        public Builder setTitle(CharSequence title) {
            P.mTitle = title;
            return this;
        }
        
        // ....
        
        // 3.构建AlertDialog, 传递参数
        public AlertDialog create() {
            // 4.因为已经通过builder设置了参数, 接下来就可以创建真正需要的AlertDialog对象
            final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
            
            // 5.将Builder类中的成员变量P应用到AlertDialog类中
            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;
        }      
    }   
}

可以看到Android源码中的AlertDialog并没有遵循GOF设计模式中经典的实现方式, 而是进行了变种, 但却使其使用更加的方便. 这里AlertDialog.Builder这个类同时扮演了范例中的builder,具体实现builder,Director的角色. 简化了Builder设计模式, 因为模块比较稳定不会存在变化, 根据具体场景简化模式, 正是体现了灵活运用设计模式的实例.

3.原型模式

3.1定义

用原型实例指定创建对象的种类,通过拷贝这个原型创建新的对象

android源码中使用到的设计模式(创建型)_第2张图片
原型模式

3.2说明

Client:客户端用户
Prototype:抽象类或者接口,声明具备clone能力。
concretePrototype:具体实现原型。

3.3使用场景

  1. 类的初始化需要消耗很多资源
  2. 通过new产生一个对象需要非常繁琐的数据准备或者访问权限
  3. 一个对象需要提供给其他对象访问,而且其他各个调用者都需要修改其值,可以通过原型拷贝多个对象提供给调用者调用。

3.4涉及到的知识点

  • 赋值:对一个对象赋值一个对象,相当于两个对象对原来的对象都有控制权炒作一个另一个也有变化
//继承Cloneable类 相当于prototype接口。wordDocument相当于ConcreteProttype拥有赋值调用
public class WordDocument implements Cloneable {
 
  // 文字
  private String mText = "";
  // 图片
  private List mImages = new ArrayList();
 
  public String getText() {
    return mText;
  }
 
  public void setText(String mText) {
    this.mText = mText;
  }
 
  public List getImages() {
    return mImages;
  }
 
  public void setImages(List mImages) {
    this.mImages = mImages;
  }
  
  public void addImage(String img) {
    this.mImages.add(img);
  }
 
  /**
   * 打印文档内容
   */
  public void showDocument() {
    System.out.println("----------- Word Content Start -----------");
    System.out.println("Text : " + mText);
    System.out.println("Images List: ");
    for (String imgName : mImages) {
      System.out.println("image name : " + imgName);
    }
    System.out.println("----------- Word Content End -----------");
  }
}

android源码中使用到的设计模式(创建型)_第3张图片
赋值
  • 浅拷贝:重写clone()方法,但是没有对引用类型进行拷贝,造成一个对象的引用类型发生变化另一个也会变化
//在类中添加clone 进行浅拷贝
  @Override
  protected WordDocument clone() {
    try {
      WordDocument doc = (WordDocument) super.clone();
      doc.mText = this.mText;
      doc.mImages = this.mImages;
      return doc;
    } catch (Exception e) {
    }
    return null;
  }

android源码中使用到的设计模式(创建型)_第4张图片
浅拷贝
  • 深拷贝:对引用类型再次进行clone()
//进行深度拷贝
ArrayList重写了clone的方法
@SuppressWarnings("unchecked")
  @Override
  protected WordDocument clone() {
    try {
      WordDocument doc = (WordDocument) super.clone();
      doc.mText = this.mText;
      //对mImages调用clone进行深度拷贝
      doc.mImages =  ((List) ((ArrayList) this.mImages).clone());
      return doc;
    } catch (Exception e) {
    }
    return null;
  }

android源码中使用到的设计模式(创建型)_第5张图片
深拷贝

3.5 Android源码对应实现

  • ArrayList源码中的clone()
public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable{
    transient Object[] elementData; 
    private int size;
    
    public Object clone() {
        try {
            ArrayList v = (ArrayList) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }
  • Intent中实现
    1.intent实现了Cloneable
public class Intent implements Parcelable, Cloneable {
}

2.对clone()重写


android源码中使用到的设计模式(创建型)_第6张图片
Intent

没有调用super.clone()使用了new Intent(this).当消耗不大的时候可以使用new

4.简单工厂模式

4.1定义

定义一个用于创建对象的接口,让子类决定实例化那个类

android源码中使用到的设计模式(创建型)_第7张图片
工厂方法模式

4.2使用场景

在任何需要创建复杂对象的地方,都可以使用工厂模式。但是能用new创建对象无需使用工厂方法模式。

4.3实现方式

一般实现流程

1.定义抽象产品类product
/** 
 * @describe 抽象产品类
 */
public abstract class Product {
 
  /**
   * 产品类的抽象方法,由具体的产品类去实现
   */
  public abstract void method();
}
2、具体的产品实现类
/** 
 * @describe 具体实现类A
 */
public class ConcreteProductA extends Product {
 
  @Override
  public void method() {
    System.out.println("我是具体的产品实现A");
  }
}
 
/** 
 * @describe 具体实现类B
 */
public class ConcreteProductB extends Product {
 
  @Override
  public void method() {
    System.out.println("我是具体的产品实现B");
  }
 
}
 
3.抽象工厂类 factory
/** 
 * @describe 抽象工厂类
 */
public abstract class Factory {
  
  /**
   * 抽象工厂类方法
   * @return 
   */
  public abstract Product CreateProuct();
}
4.具体实现工厂类
/**
 * @describe 抽象工厂类的具体实现方法
 */
public class ConcreteFactory extends Factory {
 
  @Override
  public Product CreateProuct() {
    return new ConcreteProductA();
  }
}
5.客户端调用
/**
 * @describe 调用类
 */
public class Client {
 
  public static void main(String[] args) {
    // 创建工厂
    Factory factory = new ConcreteFactory();
    // 创建产品
    Product product = factory.CreateProuct();
    // 调用产品的方法
    product.method();
  }
}

使用反射的方法进行工厂方法模式

1.创建反射工厂抽象类
/** 
 * @describe 使用反射的方便调用
 */
public abstract class Factory {
  public abstract  T createFactory(Class clz);
}
2.具体的实现工厂类
/** 
 * @describe 具体的实现工厂类
 */
public class ConCreateFactory extends Factory{
 
  @SuppressWarnings("unchecked")
  @Override
  public  T createFactory(Class clz) {
    Product p = null;
    try {
      p = (Product) Class.forName(clz.getName()).newInstance();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
    return (T) p;
  }
3.调用方法
/**
 * @describe 调用类
 */
public class Client {
 
  public static void main(String[] args) {
    // 创建工厂
    Factory factory = new ConCreateFactory();
    // 创建产品
    Product product = factory.createFactory(ConcreteProductB.class);
    // 调用产品的方法
    product.method();
  }
}
}

4.3 android中的简单工厂方法模式

onCreate是一个工厂方法

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new FrameLayout(this));   
    }
}

通过onCrete这个方法,我们可以构建出任何样式的根布局。我们在不同的Activity#onCreate()方法将设置的布局通过setContentView()函数传递给frameworks并显示出来. 这不就是一个工厂模式的结构. 方法内部可以创建不同的对象, 产生不同的实例.

service中的onBind()也可以看成工厂方法模式

5.抽象工厂模式

5.1定义

为创建一组相关或者相互依赖的对象提供一个接口,而不需要指定它们的具体类

android源码中使用到的设计模式(创建型)_第8张图片
抽象工厂模式

5.2Android源码对应实现

抽象工厂在Android实现较少,基本上都可以用工厂方法模式解决。MediaPlayer底层使用的是抽象工厂模式

android源码中使用到的设计模式(创建型)_第9张图片
MediaPlayer

你可能感兴趣的:(android源码中使用到的设计模式(创建型))