为啥说上面这句话呢,因为所谓的设计模式其实就是套路,套路呢还比较受大家喜欢。
为啥使用设计模式呢,无非高内聚低耦合。
Android中的MVC
Android中界面部分也采用了当前比较流行的MVC框架,在Android中:
-
视图层(View)
一般采用XML文件进行界面的描述,这些XML可以理解为AndroidApp的View。使用的时候可以非常方便的引入。同时便于后期界面的修改。逻辑中与界面对应的id不变化则代码不用修改,大大增强了代码的可维护性。
-
控制层(Controller)
Android的控制层的重任通常落在了众多的Activity的肩上。这句话也就暗含了不要在Activity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Actiivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
-
模型层(Model)
我们针对业务模型,建立的数据结构和相关的类,就可以理解为AndroidApp的Model,Model是与View无关,而与业务相关的(感谢@Xander的讲解)。对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。
MVP从更早的MVC框架演变过来,与MVC有一定的相似性:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。
MVP框架由3部分组成:View负责显示,Presenter负责逻辑处理,Model提供数据。在MVP模式里通常包含3个要素(加上View interface是4个):
-
View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity)
-
Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合)
-
Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
-
*View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试
两种模式的主要区别:
-
(最主要区别)View与Model并不直接交互,而是通过与Presenter交互来与Model间接交互。而在MVC中View可以与Model直接交互
-
通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑。而Controller是基于行为的,并且可以被多个View共享,Controller可以负责决定显示哪个View
-
Presenter与View的交互是通过接口来进行的,更有利于添加单元测试。
设计模式文章https://www.cnblogs.com/cr330326/p/5627658.html
1,工厂模式
工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。
public interface Sender {
public void Send();
}
其次,创建实现类:
public class MailSender implements Sender {
@Override
public void Send() {
System.out.println("this is mailsender!");
}
}
public class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("this is sms sender!");
}
}
public class SendFactory {
public static Sender produceMail(){
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
public class FactoryTest {
public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.Send();
}
}
2,单例模式
单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
饿汉式-程序加载class文件的时候对象就会被创建,线程不安全
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance; }
懒汉式-使用的时候才会被创建,线程安全双重锁
public static Singleton getInstance() {
if (instance == null) {
synchronized (instance) {
if (instance == null) {
instance = new Singleton(); } } }
return instance; }
3,Bulider模式
public class PersonThree {
//固定不变的对象,一般变量需要声明为 final
private final String mName; //必选,final 类型需要在 构造器中初始化,不允许不初始化它的构造器存在
private String mLocation; //可选
private String mJob; //可选
private String mHabit; //可选
/**
* 构造方法的参数是它的 静态内部类,使用静态内部类的变量一一赋值
* @param builder
*/
public PersonThree(Builder builder) {
this.mName = builder.mName;
this.mLocation = builder.mLocation;
this.mJob = builder.mJob;
this.mHabit = builder.mHabit;
}
/**
* PersonTree 的静态内部类,成员变量和 PersonTree 的一致
*/
public static class Builder{
private final String mName; //必选,final 类型需要在 构造器中初始化,不允许不初始化它的构造器存在
private String mLocation; //可选
private String mJob; //可选
private String mHabit; //可选
/**
* 含必选参数的构造方法
* @param name
*/
public Builder(String name) {
mName = name;
}
public Builder setLocation(String location) {
mLocation = location;
return this;
}
public Builder setJob(String job) {
mJob = job;
return this;
}
public Builder setHabit(String habit) {
mHabit = habit;
return this;
}
/**
* 最终构建方法,返回一个 PersonTree 对象,参数是当前 Builder 对象
* @return
*/
public PersonThree build(){
return new PersonThree(this);
}
}
}
调用:
new PersonThree.Builder("shixinzhang")
.setLocation("Shanghai")
.setJob("Android Develop")
.setHabit("LOL")
.build();
4,适配器模式
即列表传入不同的数据显示不同的列表展示
5,代理模式
代理模式就是多一个代理类出来,替原对象进行一些操作,比如处理按钮的多次点击
public class ClickProxyimplements View.OnClickListener {
private View.OnClickListenerorigin;
private long last_click =0;
private long time_ms =1000; //ms
private IAgainmIAgain;
public ClickProxy(View.OnClickListener origin, long time_ms, IAgain again) {
this.origin = origin;
this.mIAgain = again;
this.time_ms = time_ms;
}
public ClickProxy(View.OnClickListener origin) {
this.origin = origin;
}
@Override
public void onClick(View v) {
if (System.currentTimeMillis() -last_click >=time_ms) {
origin.onClick(v);
last_click = System.currentTimeMillis();
}else {//重复点击
if (mIAgain !=null)mIAgain.onAgain();
}
}
public interface IAgain {
void onAgain();//重复点击
}
}
btn_notification.setOnClickListener(new ClickProxy(new View.OnClickListener() {
@Override
public void onClick(View v) {
}}));
6,观察者模式
按钮点击
刚学安卓的时候 ,按钮点击是必不可少的 ,我们先来回顾一下其中的套路
相信大家对此都不陌生了
如果你连这个都没有写的很熟练 ,那此篇文章可能不适合你了
//寻找控件 Button bt = (Button) findViewById(R.id.bt);//实例化一个监听 View.OnClickListener clickListener =newView.OnClickListener() {@OverridepublicvoidonClick(View view){//点击事件 //your code } };//为按钮控件设置点击监听 bt.setOnClickListener(clickListener );
当然这样做的目的是为了更好的理解观察者模式
在这里 我们称 Button 为 被观察者 ( Observable )
这个单词还是很重要的 RxJava 里面还会用到
当然可想而知 OnClickListener 就是观察者 ( Observer ) 了
被观察者可以有多个观察者 这个叫做订阅机制 (Subscribe)
当被观察者的状态发生改变 观察者就做出相应的动作
这个就叫做 观察者模式
Android设计模式系列-组合模式
将对象View和ViewGroup组合成树形结构以表示"部分-整体"的层次结构(View可以做为ViewGroup的一部分,ViewGroup也可以被用户当做一 个view)。组合模式使得用户对单个对象View和组合对象ViewGroup的使用具有一致性。
Android设计模式系列-单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点,synchronized关键字,在多线程的环境下,单例模式为了保证自己实例数量的唯一,必然会做并发控制,多线程下的线程安全。
(1).创建型模式。
(2).对唯一实例的受控访问。
(3).避免全局变量污染命名空间。
(4).允许对操作和表示的精化。
(5).比类操作更灵活。
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
public static synchronized Singleton getInstance() {
//也可以这样写:synchronized public static Singleton getInstance() {
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
避免单例引起的内存泄漏
private static DisplayUtils instance = null;
private Context mContext;
private DisplayUtils(Context context) { //这里变化了,把当前Context指向个应用程序的Context
this.mContext = context.getApplicationContext();
}
public static DisplayUtils getInstance(Context context) {
if (instance == null) {
synchronized (DisplayUtils.class) {
if (instance == null) {
instance = new DisplayUtils(context);
}
}
}
return instance;
}
弱引用的使用
private WeakReference<Context> weakContext;
private DisplayUtils(Context context) { //这里变化了,把当前Context指向个应用程序的Context
weakContext = new WeakReference<Context>(context);
}
public static DisplayUtils getInstance(Context context) {
if (instance == null) {
synchronized (DisplayUtils.class) {
if (instance == null) {
instance = new DisplayUtils(context);
}
}
}
return instance;
}
public int dip2px(float dpValue) {
final float scale = weakContext.get().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
Android设计模式系列--工厂方法模式
public interface Factory{
public Product create();
}
我们再来定义一个产品接口
- public interface Product{}
一下是实现了产品接口的产品类
- public class Washer implements Product{
- public Washer(){
- System.out.println("洗衣机被制造了");
- }
- }
- public class Icebox implements Product{
- public Icebox(){
- System.out.println("冰箱被制造了");
- }
- }
- public class AirCondition implements Product{
- public Icebox(){
- System.out.println("空调被制造了");
- }
- }
接下来,就是工厂方法的核心部分,也就是具体创建产品对象的具体工厂类,
- //创建洗衣机的工厂
- public class CreateWasher implements Factory{
- public Product create(){
- return new Washer();
- }
- }
- //创建冰箱的工厂
- public class CreateIcebox implements Factory{
- public Product create(){
- return new Icebox();
- }
- }
- //创建空调的工厂
- public class CreateAirCondition implements Factory{
- public Product create(){
- return new AirCondition();
- }
- }
Android设计模式系列-适配器模式
适配器模式,把一个类的接口变换成客户端所期待的另一种接口,从而使原本不匹配而无法在一起工作的两个,类能够在一起工作。
适配器模式分为类适配器模式和对象适配器模式。
Android设计模式系列--观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
观察者模式里面目标类维护了所有观察者的引用,而回调里面只是维护了一个引用
比如说广播--广播接受者,就是观察者模式,发起广播,所有注册的广播接受者都会收到。
button点击,广播接受者
Android设计模式系列--Builder模式
在Android中经常要使用AlertDialog来显示一些简单的窗口,通常的写法类似下面的代码 :
[java] view plain copy
- AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).setTitle("提示")
- .setMessage("确定退出?").create();
- dialog.show();
可以看到dialog是通过Builder创建的,那么Builder是如何同AlertDialog协同工作的呢?其实AlertDialog的创建就是使用Builder模式,废话不多说,直接上代码吧。
[java] view plain copy
- package com.umeng.dp.builder;
- /**
- * @Copyright: Umeng.com, Ltd. Copyright 2011-2015, All rights reserved
- * @Title: UmengDialog.java
- * @Package com.umeng.dp.builder
- * @Description: Builder模式
- * @author Honghui He
- * @version V1.0
- */
- public class UmengDialog {
- private String mTitle = "";
- private String mMessage = "";
- private int mIcon = -1;
- /**
- * @Title: UmengDialog
- * @Description: UmengDialog Constructor
- * @param builder 将dialog参数传递给builder,够将好的builder传递给Dialog
- */
- private UmengDialog(Builder builder) {
- mTitle = builder.getTitle();
- mMessage = builder.getMessage();
- mIcon = builder.getIcon();
- }
- /**
- * @Title: show
- * @Description: show dialog
- * @throws
- */
- public void show() {
- System.out.println("显示窗口 : " + this);
- }
- /**
- * (非 Javadoc)
- *
- * @Title: toString
- * @Description:
- * @return
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return "UmengDialog [mTitle=" + mTitle + ", mMessage=" + mMessage + ", mIcon=" + mIcon
- + "]";
- }
- /**
- * @ClassName: Builder
- * @Description: Builder模式, 用于构建复杂的对象
- * @author Honghui He
- */
- public static class Builder {
- private String mDlgTitle = "";
- private String mDlgMessage = "";
- private int mDlgIcon = -1;
- /**
- * @Title: Builder
- * @Description: Builder Constructor
- */
- public Builder() {
- }
- /**
- * 获取 mDlgTitle
- *
- * @return 返回 mDlgTitle
- */
- public String getTitle() {
- return mDlgTitle;
- }
- /**
- * 设置 mDlgTitle
- *
- * @param 对mDlgTitle进行赋值
- */
- public Builder setTitle(String title) {
- this.mDlgTitle = title;
- return this;
- }
- /**
- * 获取 mDlgMessage
- *
- * @return 返回 mDlgMessage
- */
- public String getMessage() {
- return mDlgMessage;
- }
- /**
- * 设置 mDlgMessage
- *
- * @param 对mDlgMessage进行赋值
- */
- public Builder setMessage(String msg) {
- this.mDlgMessage = msg;
- return this;
- }
- /**
- * 获取 mDlgIcon
- *
- * @return 返回 mDlgIcon
- */
- public int getIcon() {
- return mDlgIcon;
- }
- /**
- * 设置 mDlgIcon
- *
- * @param 对mDlgIcon进行赋值
- */
- public Builder setIcon(int resId) {
- this.mDlgIcon = resId;
- return this;
- }
- /**
- * @Title: create
- * @Description: 创建窗口
- * @throws
- */
- public UmengDialog create() {
- return new UmengDialog(this);
- }
- }
- }
public class PersonThree {
//固定不变的对象,一般变量需要声明为 final
private final String mName; //必选,final 类型需要在 构造器中初始化,不允许不初始化它的构造器存在
private String mLocation; //可选
private String mJob; //可选
private String mHabit; //可选
/**
* 构造方法的参数是它的 静态内部类,使用静态内部类的变量一一赋值
* @param builder
*/
public PersonThree(Builder builder) {
this.mName = builder.mName;
this.mLocation = builder.mLocation;
this.mJob = builder.mJob;
this.mHabit = builder.mHabit;
}
/**
* PersonTree 的静态内部类,成员变量和 PersonTree 的一致
*/
public static class Builder{
private final String mName; //必选,final 类型需要在 构造器中初始化,不允许不初始化它的构造器存在
private String mLocation; //可选
private String mJob; //可选
private String mHabit; //可选
/**
* 含必选参数的构造方法
* @param name
*/
public Builder(String name) {
mName = name;
}
public Builder setLocation(String location) {
mLocation = location;
return this;
}
public Builder setJob(String job) {
mJob = job;
return this;
}
public Builder setHabit(String habit) {
mHabit = habit;
return this;
}
/**
* 最终构建方法,返回一个 PersonTree 对象,参数是当前 Builder 对象
* @return
*/
public PersonThree build(){
return new PersonThree(this);
}
}
}
调用:
new PersonThree.Builder("shixinzhang")
.setLocation("Shanghai")
.setJob("Android Develop")
.setHabit("LOL")
.build();
Android设计模式系列--生产者消费者模式
/**
* 生产者消费者模式:使用Object.wait() / notify()方法实现
*/
public class ProducerConsumer {
private static final int CAPACITY = 5;
public static void main(String args[]){
Queue<Integer> queue = new LinkedList<Integer>();
Thread producer1 = new Producer("P-1", queue, CAPACITY);
Thread producer2 = new Producer("P-2", queue, CAPACITY);
Thread consumer1 = new Consumer("C1", queue, CAPACITY);
Thread consumer2 = new Consumer("C2", queue, CAPACITY);
Thread consumer3 = new Consumer("C3", queue, CAPACITY);
producer1.start();
producer2.start();
consumer1.start();
consumer2.start();
consumer3.start();
}
/**
* 生产者
*/
public static class Producer extends Thread{
private Queue<Integer> queue;
String name;
int maxSize;
int i = 0;
public Producer(String name, Queue<Integer> queue, int maxSize){
super(name);
this.name = name;
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run(){
while(true){
synchronized(queue){
while(queue.size() == maxSize){
try {
System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("[" + name + "] Producing value : +" + i);
queue.offer(i++);
queue.notifyAll();
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 消费者
*/
public static class Consumer extends Thread{
private Queue<Integer> queue;
String name;
int maxSize;
public Consumer(String name, Queue<Integer> queue, int maxSize){
super(name);
this.name = name;
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run(){
while(true){
synchronized(queue){
while(queue.isEmpty()){
try {
System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
int x = queue.poll();
System.out.println("[" + name + "] Consuming value : " + x);
queue.notifyAll();
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
/**
* 生产者消费者模式:使用Lock和Condition实现
* {@link java.util.concurrent.locks.Lock}
* {@link java.util.concurrent.locks.Condition}
*/
public class ProducerConsumerByLock {
private static final int CAPACITY = 5;
private static final Lock lock = new ReentrantLock();
private static final Condition fullCondition = lock.newCondition(); //队列满的条件
private static final Condition emptyCondition = lock.newCondition(); //队列空的条件
public static void main(String args[]){
Queue<Integer> queue = new LinkedList<Integer>();
Thread producer1 = new Producer("P-1", queue, CAPACITY);
Thread producer2 = new Producer("P-2", queue, CAPACITY);
Thread consumer1 = new Consumer("C1", queue, CAPACITY);
Thread consumer2 = new Consumer("C2", queue, CAPACITY);
Thread consumer3 = new Consumer("C3", queue, CAPACITY);
producer1.start();
producer2.start();
consumer1.start();
consumer2.start();
consumer3.start();
}
/**
* 生产者
*/
public static class Producer extends Thread{
private Queue<Integer> queue;
String name;
int maxSize;
int i = 0;
public Producer(String name, Queue<Integer> queue, int maxSize){
super(name);
this.name = name;
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run(){
while(true){
//获得锁
lock.lock();
while(queue.size() == maxSize){
try {
System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
//条件不满足,生产阻塞
fullCondition.await();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("[" + name + "] Producing value : +" + i);
queue.offer(i++);
//唤醒其他所有生产者、消费者
fullCondition.signalAll();
emptyCondition.signalAll();
//释放锁
lock.unlock();
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 消费者
*/
public static class Consumer extends Thread{
private Queue<Integer> queue;
String name;
int maxSize;
public Consumer(String name, Queue<Integer> queue, int maxSize){
super(name);
this.name = name;
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run(){
while(true){
//获得锁
lock.lock();
while(queue.isEmpty()){
try {
System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer");
//条件不满足,消费阻塞
emptyCondition.await();
} catch (Exception ex) {
ex.printStackTrace();
}
}
int x = queue.poll();
System.out.println("[" + name + "] Consuming value : " + x);
//唤醒其他所有生产者、消费者
fullCondition.signalAll();
emptyCondition.signalAll();
//释放锁
lock.unlock();
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}