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

单例设计模式

概念

单例模式(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
            }
        });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值