andorid用到的常见的Java设计模式

来源:互联网 发布:淘宝客邮件推广 编辑:程序博客网 时间:2024/06/05 13:29

单例设计模式

概念

单例模式(Singleton)主要作用是保证在Java应用程序中,一个类只有一个实例存在。

如何实现

  1. 私有的构造方法,可以防止多个实例产生,英文私有,其他类无法new该类。
  2. 私有静态实例变量,私有是防止外部滞空,下面要说到的静态的方法不能访问非静态变量。
  3. 公有的静态访问方法,公有是因为要提供对外访问,静态是因为该类不能在外部实例化。
public class MySingleTon {        // 单例(singleton)=1.私有的构造方法+2.私有静态实例变量+3.公有的静态访问方法        private MySingleTon() {        }        private  static MySingleTon mySingleTon = new MySingleTon();        public static MySingleTon getInstance() {            return mySingleTon;        }    }

懒汉和饿汉模式

说到单例模式就得提到懒汉和饿汉模式,饿汉模式是上来就搞对象,不考虑是否使用就直接分配内存,上面的代码就是饿汉模式。而懒汉模式则是需要时才搞对象,这可以避免内存浪费。

public class MySingleTon {        // 单例(singleton)=1.私有的构造方法+2.私有静态实例变量+3.公有的静态访问方法        private MySingleTon() {        }        private  static MySingleTon mySingleTon = null;        public static MySingleTon getInstance() {            if(mySingleTon==null){                mySingleTon=new MySingleTon();            }            return mySingleTon;        }    }

不过懒汉模式是线程不安全的。假如现在有两个线程,线程中都有这句代码

MySingleTon mySingleTon=MySingleTon.getInstance();

线程1运行到了if(mySingleTon==null)时被线程2抢去了,线程2同样运行到了if(mySingleTon==null)时被线程1抢去了,这时问题就发生了,由于线程1在被抢之前就已经判断了mySingTon不为空,这时就会实例mySingleTom,而但线程2重新抢到执行权时,它也已经完成非空的判断,并会往下,又实例了一遍mySingleTom,此时程序中就产生了两个实例,这与我们所期望的不同。对此,正确的做法是采用双重锁来处理

public static LazySingleTon2 getInstance() {        if (sSingleTon == null) {//提交效率,如果不为空,直接return            synchronized (LazySingleTon2.class) {//代码线程安全                if (sSingleTon == null) {                    sSingleTon = new LazySingleTon2();                }            }        }        return sSingleTon;    }

Android 系统里在服务方面大量使用单例
TelephonyManager里的代码:

    /** @hide */    private TelephonyManager() {    }    private static TelephonyManager sInstance = new TelephonyManager();    /** @hide    /* @deprecated - use getSystemService as described above */    public static TelephonyManager getDefault() {        return sInstance;    }

适配器模式

概念

将控件(Adaptee(被适配者))与内容(Adaptor(适配器))相分离的一种设计
Adaptee(被适配者):ListView ,GridView,Gallery,ViewPager,….
Adaptor(适配器):SimpleAdapter ,CursorAdapter,ArrayAdapter BaseAdapter
一般通过Adaptee.setadapter(Adaptor)来绑定。

观察者模式

概念

一个目标对象(Observable)会发生敏感数据的变化,通常我们需要获取该数据,创建一个观察者对象(Observer)放置到目标内部,一旦有数据变化,就及时获取,很多地方都用到了观察者模式,比如当我们取钱时,会受到到银行的短信通知,我们追的剧更新了,收到系统的通知

如何实现

  1. 确定目标对象(Observable),发生敏感数据变化
  2. 目标对象得继承Observable,extends Observable,但目标发生变化是,要setChanged,要通知观察者notifyObservers(Object Data);
public class TemperatureObservable extends Observable {    private int temperature = 0;    public void start() {        //模拟温度每秒提升1度        for (int i = 0; i < 100; i++) {            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            temperature++;//数据变化            setChanged();//标记            notifyObservers(temperature);//通知观察者        }    }}

3.写观察者,implements Observer,重写public void update(Observable observable, Object data)方法,其中observable为目标对象,data为目标对象中notifyObservers传进的obj。

public class DisPlayer implements Observer{    //接收数据变化 的方法     @Override    public void update(Observable observable, Object data) {        int temperature=(Integer) data;        System.out.println("显示屏幕:"+temperature+"度");        }}

4.为目标对象设置观察者

        //温度实例        TemperatureObservable temperatureObservable =new TemperatureObservable();        //显示屏幕        DisPlayer displayer=new DisPlayer();        //添加        temperatureObservable.addObserver(displayer);        temperatureObservable.start();

我们常见的ListView里就用了观察者模式,当数据发生变化时,通过adapter.notifyDataSetChanged()通知listview刷新。

public class MainActivity extends Activity implements View.OnClickListener {    private ListView lv;    private Button bt;    private List<String> list;    ArrayAdapter<String> adapter;    View footview;    int i=0;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        list=new ArrayList<String>();        for(;i<20;i++){            //初始数据为0-19            list.add(i+"");        }        lv=(ListView) findViewById(R.id.lv);        footview=View.inflate(MainActivity.this, R.layout.listviewfoot, null);        //添加listview的地步视图,加载更多按钮,当滚到listview最底边的时候会看到        lv.addFooterView(footview);        bt=(Button) findViewById(R.id.bt);        bt.setOnClickListener(this);        adapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, list);        lv.setAdapter(adapter);    }    @Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch (v.getId()) {        case R.id.bt:            //假数据,一次加载20条数据            int j=i;            for(;i<j+20;i++){                list.add(i+"");            }            //通知更新            adapter.notifyDataSetChanged();            break;        default:            break;        }    }}

现在的加载更多更多的是采用手势的方式,往上拉实现加载更多。
android还有四大组件之一的内容提供者ContentProvider也使用了观察者模式

public class MainActivity extends Activity {    private TextView sms_tv;    ContentResolver resolver;    MyObserver observer;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        sms_tv=(TextView) findViewById(R.id.sms_tv);        resolver=getContentResolver();        Uri uri=Uri.parse("Content://sms/");        observer=new MyObserver(new Handler());        //注册内容观察者        //resolver.registerContentObserver(观察的uri, 为ture表示uri子路径也属于观察范围,false则不属于, observer)        resolver.registerContentObserver(uri, true, observer);    }    //内容观察者    class MyObserver extends ContentObserver{        public MyObserver(Handler handler) {            super(handler);            // TODO Auto-generated constructor stub        }        //当内容观察者观察到数据库的内容变化了,调用这个方法        @Override        public void onChange(boolean selfChange) {            // TODO Auto-generated method stub            super.onChange(selfChange);            Toast.makeText(MainActivity.this, "数据库内容发生变化了", 1).show();            Uri uri=Uri.parse("content://sms/");            ContentResolver resolver=getContentResolver();            Cursor cursor=resolver.query(uri, new String[]{"address","date","type","body"}, null, null, null);            //因为短信是倒序排列,因此获取最新一个就是第一个            cursor.moveToFirst();            String address=cursor.getString(cursor.getColumnIndex("address"));            String body=cursor.getString(cursor.getColumnIndex("body"));            sms_tv.setText("短信内容:"+body+"\n短信地址:"+address);            cursor.close();        }    }    @Override    protected void onDestroy() {        // TODO Auto-generated method stub        super.onDestroy();        if(resolver!=null){            resolver.unregisterContentObserver(observer);        }        observer=null;        resolver=null;    }}

事件驱动模型

两大机制

  1. 事件驱动/监听器,如点击事件 setOnclick(Listener)
  2. 回调机制 , 点击事件传进的接口实例会回调onClick(View v)

概念

事件驱动模型=事件源+监听器+事件处理
1. 事件源:接收事件的对象,如控件
2. 监听器:设置在事件源内部,捕获事件转换成参数,如点击事件的监听器为onClickListener
3. 事件处理,监听器回调函数

bt=(Button) findViewById(R.id.bt);        bt.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                // TODO Auto-generated method stub                  }        });

监听器一般有四种写法,可以看这里
监听器四种写法

Command 模式

概念

Command命令模式,主要是降低控件与事件处理程序之间的耦合性,我们平常常见的按钮Button,就用了Command命令模式,让控件与事件相分离,所以Button什么场合都能用

实现步骤

public class MyButton {    // 1.申明一个接口interface    interface MyOnClickListener{        // 2.定义接口方法参数        public void MyOnClick(View view);    }    // 3.控件内部声明成员变量(监听器)    private MyOnClickListener listener=null;    // 4.通过set方法设置监听器对象    public void setMyOnClickListener(MyOnClickListener l){        this.listener=l;    }}
//在系统调用的地方调用方法,是不是跟平常点击事件写法一样        MyButton button=new MyButton();        button.setMyOnClickListener(new MyOnClickListener() {                   @Override            public void MyOnClick(View view) {                // TODO Auto-generated method stub            }        });
0 0
原创粉丝点击