【设计模式】
设计模式(适用场景 优点)
单例模式
确保单例类只有一个实例,并且这个单例类提供一个函数接口让其他类获取到这个唯一的实例。
什么时候需要使用单例模式呢:如果某个类,创建时需要消耗很多资源,即new出这个类的代价很大;或者是这个类占用很多内存,如果创建太多这个类实例会导致内存占用太多。
//此为懒汉式 饿汉式在声明时直接初始化
public class Singleton{
//volatile保证了其他线程拿到的也是最新的实例
private volatile static Singleton instance;
//将默认的构造函数私有化,防止其他类手动new
private Singleton(){};
public static Singleton getInstance(){
if(instance==null){
sychronized(Singleton.class){
if(instance==null)
instance=new Singleton();
}
}
return instatnce;
}
}
使用类级内部类,只有内部类被调用到(即Singleton.singleton)才会装载
public class MySingleton {
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定的关系,而且只有被调用到才会装载,从而实现了延迟加载
*/
private static class Singleton{
/**
* 静态初始化器,用JVM来保证线程安全
*/
private static MySingleton singleton = new MySingleton();
static {
System.out.println("---->类级的内部类被加载");
}
private Singleton(){
System.out.println("---->类级的内部类构造函数被调用");
}
}
//私有化构造函数
private MySingleton(){
System.out.println("-->开始调用构造函数");
}
public static MySingleton getInstance(){
System.out.println("-->开始调用公有方法返回实例");
System.out.println("-->返回单例");
return Singleton.singleton;
}
}
记忆:getSystemService的内部实现
创造者模式(Builder)
将一个复杂对象的构造与它的表示分离,使得同样的构造过程可以创建不同的表示。
主要是在创建某个对象时,需要设定很多的参数(通过setter方法),但是这些参数必须按照某个顺序设定,或者是设置步骤不同会得到不同结果
记忆:在创建对话框时的代码
工厂方法模式
定义一个创建对象的接口,让子类决定实例化哪个类
其实,在getSystemService方法中就是用到了工厂模式,他就是根据传入的参数决定创建哪个对象,当然了,由于返回的都是以单例模式存在的对象,因此不用new了,直接把单例返回就好。
抽象工厂模式
为创建一组相关或者是相互依赖的对象提供一个接口,而不需要制定他们的具体类 (满足依赖倒置原则)
public abstract class AbstractProductA{
public abstract void method();
}
public abstract class AbstractProdectB{
public abstract void method();
}
public abstract class AbstractFactory{
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}
public class ConcreteFactory1 extends AbstractFactory{
public AbstractProductA createProductA(){
return new ConcreteProductA1();
}
public AbstractProductB createProductB(){
return new ConcreteProductB1();
}
}
public class ConcreteFactory2 extends AbstractFactory{
public AbstractProductA createProductA(){
return new ConcreteProductA2();
}
public AbstractProductB createProductB(){
return new ConcreteProductB2();
}
}
策略模式
有一系列的算法,将每个算法封装起来(每个算法可以封装到不同的类中),各个算法之间可以替换,策略模式让算法独立于使用它的客户而独立变化。
其中在属性动画中使用时间插值器的时候就用到了。在使用动画时,你可以选择线性插值器、加速减速插值器、减速插值器以及自定义的插值器。这些插值器都是实现根据时间流逝的百分比来计算出当前属性值改变的百分比。通过根据需要选择不同的插值器,实现不同的动画效果。
适配器模式
定义:把一个类的接口变换成客户端所期待的另一个接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
比较典型的有ListView和RecyclerView。为什么ListView需要使用适配器呢?主要是,ListView只关心它的每个ItemView,而不关心这个ItemView具体显示的是什么。而我们的数据源存放的是要显示的内容,它保存了每一个ItemView要显示的内容。ListView和数据源之间没有任何关系,这时候,需要通过适配器,适配器提供getView方法给ListView使用,每次ListView只需提供位置信息给getView函数,然后getView函数根据位置信息向数据源获取对应的数据,根据数据返回不同的View。
观察者模式
定义:定义了对象之间的一对多的关系,其实就是1对n,当“1”发生变化时,“n”全部得到通知,并更新。
观察者模式一个比较经典的应用就是:订阅——发布系统。很容易理解,发布消息时,将消息发送给每个订阅者。
那么Android哪里用到了观察者模式呢?我们看看ListView的适配器,有个函数notifyDataSetChanged()函数,这个函数其实就是通知ListView的每个Item,数据源发生了变化,请各位Item重新刷新一下。
装饰模式
动态的给一个对象添加额外的职责,就增加功能来说,装饰模式比子类继承的方式更灵活。
通过简单代码来理解装饰模式:
public abstract class Component{
public abstract void operate();
}
public class ConcreteComponent extends Component{
public void operate(){
//具体的实现
}
}
public class Decorator{
private Component component;
public Decorator(Component component){
this.component=component;
}
public void operate(){
operateA();
component.operate();
operateB();
}
public void operateA(){
//具体操作
}
public void operateB(){
//具体操作
}
}