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定义
把一个复杂的类的构建过程和它的表示进行分离
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使用场景
- 相同的方法,不同的执行顺序,产生不同的事件结果
- 多个部件或者零件,都可以配装到一个对象,但是产生的运行结果不同
- 当初始化一个对象特别复杂,参数多,且很多参数默认的时候
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定义
用原型实例指定创建对象的种类,通过拷贝这个原型创建新的对象
3.2说明
Client:客户端用户
Prototype:抽象类或者接口,声明具备clone能力。
concretePrototype:具体实现原型。
3.3使用场景
- 类的初始化需要消耗很多资源
- 通过new产生一个对象需要非常繁琐的数据准备或者访问权限
- 一个对象需要提供给其他对象访问,而且其他各个调用者都需要修改其值,可以通过原型拷贝多个对象提供给调用者调用。
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 -----------");
}
}
- 浅拷贝:重写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;
}
- 深拷贝:对引用类型再次进行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;
}
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()重写
没有调用super.clone()使用了new Intent(this).当消耗不大的时候可以使用new
4.简单工厂模式
4.1定义
定义一个用于创建对象的接口,让子类决定实例化那个类
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定义
为创建一组相关或者相互依赖的对象提供一个接口,而不需要指定它们的具体类
5.2Android源码对应实现
抽象工厂在Android实现较少,基本上都可以用工厂方法模式解决。MediaPlayer底层使用的是抽象工厂模式