详细代码请见https://github.com/zackLangChina/DesignPatternLearning
Android与设计模式(1)
单例模式 ** 工厂模式 ** 策略模式 ** 命令模式
Android与设计模式(2)
观察者模式 ** 备忘录模式 ** 模板方法模式 ** 中介者模式
Android与设计模式(3)
代理模式 ** 适配器模式 ** 装饰模式 ** 享元模式
Android与设计模式(4)
外观模式 ** 桥接模式 ** MVP模式
0,本文的目的
设计模式的意义,在于使用额外的代码对我们的业务功能进行封装,以实现面向对象的六大原则,便于维护。
但是,脱离实际应用场景去学习这些设计模式,无异于小和尚念经,学了就忘,就算不忘,也不知道什么时候拿出来用。
此系列文章,希望和大家一起联系Android中的实际应用场景来学习设计模式,并使用简单的demo代码实现设计模式的使用。
1,单例模式
使用场景:
用于只有唯一实例的类。
Android中的应用:
服务类均为单例
代码示例:
//饿汉模式(预先实例化)
class SinglePatternHunger {
public static SinglePatternHunger amInstant = new SinglePatternHunger();
private SinglePatternHunger() { System.out.println("I am SinglePatternHunger");}
public static SinglePatternHunger getInstance() {
return amInstant;
}
}
//懒汉模式(调用时才实例化)
//静态内部类和非静态内部类一样,都是在被调用时才会被加载
//可以保证getInstance调用时才实例化外部类,实现懒汉单例模式
class SinglePatternLazy {
private SinglePatternLazy() {System.out.println("I am SinglePatternLazy");}
public static synchronized SinglePatternLazy getInstance() {
return InstantHolder.mInstant;
}
private static class InstantHolder {
private static SinglePatternLazy mInstant = new SinglePatternLazy();
}
}
2,工厂模式
使用场景:
使客户不需要知道具体的产品,告诉工厂想要哪种类型的产品,由工厂代为选择。适用于具体生产的产品可能更换的场景。
例如:
有一个专门针对有矿用户(客户)的手机店(工厂),用户来买手机,每次都跟老板说,给我来个最贵的!第一年,工厂给的都是iphone11(product),第二年都变iphone12(product)了。我们不需要更改客户的代码,只需要把工厂里生产的产品替换掉(改变产生接口返回的具体产品)就可以了。
当然,一个工厂可以生产多种产品,比如上面的手机店,可以设计成不但可以生产”最贵的“手机,也能同时生产”最便宜“的手机,客户进门后喊一嗓子:”最贵的“就给拿个大iphone,喊”最便宜的“就给拿个老人机。
Android中的应用:
BitmapFactory
代码示例:
//具体工厂类
class NiuBiFactory implements Factory{
@Override
public Production product() {
return new MostNiuBiProduction();
}
}
//工厂接口
interface Factory {
Production product();
}
//产品基类
abstract class Production {
}
//被淘汰不再生产的产品,从工厂撤下来了
class NiuBiProduction extends Production {
public NiuBiProduction() {
System.out.println("product NiuBiProduction");
}
}
//目前生产的产品,通过工厂生产
class MostNiuBiProduction extends Production {
public MostNiuBiProduction() {
System.out.println("product MostNiuBiProduction");
}
}
3,策略模式
使用场景:
一般用于算法选择。
客户通过策略模式的类调用”去噪“算法,但并不关心是使用哪种去噪算法,那么策略模式类可以根据需要,从多种去噪算法种选择一种去噪算法供客户调用。
这样,就可以方便地为客户的调用进行定制,并且之后有更新更好的算法加入,也可以不修改客户代码而使客户享受到最新的算法。
Android中的应用:
方法中根据用户Android系统的版本,执行不同的代码以实现相同的功能。这也算一种策略模式吧,因为客户端可以使用同一个接口,由策略类为客户选择执行的代码。
代码示例:
//策略类
public class StrategyPattern {
private Denoising curDenoiseStrategy = new NiubiDenoising();
public void doDenoise() {
//客户端不知道具体用哪个Denoising接口实现类,由策略类选择
curDenoiseStrategy.doDenoise();
}
}
//算法接口
interface Denoising {
void doDenoise();
}
//具体算法
class NiubiDenoising implements Denoising {
@Override
public void doDenoise() {
System.out.println("Do Denoise fast and nice!");
}
}
4,命令模式
使用场景:
命令模式将每个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;将请求进行排队或者记录请求日志,以及支持可撤销操作。
即,将命令封装并存储,以便按顺序执行或中途修改删除。
Android中的应用:
Message和Handler的组合,就是命令模式。将命令封装为Message,通过Looper中的MessageQueue存储,最终给到Handler执行。
代码示例:
import java.util.ArrayList;
import java.util.List;
//命令接口
interface Command {
public void execute();
}
//具体命令:开火!
class FireCommand implements Command {
@Override
public void execute() {
System.out.println("Fire !!");
}
}
//具体命令:停火!
class StopCommand implements Command {
@Override
public void execute() {
System.out.println("Stop !!");
}
}
//指挥官,负责下达(实例化)命令给执行者
class commander {
private List<Command> commandList = new ArrayList<Command>();
private Soldier mSoldier;
public commander(Soldier soldier) {
mSoldier = soldier;
//将命令放入队列
commandList.add(new FireCommand());
commandList.add(new StopCommand());
//按顺序执行
for (Command cmd : commandList) {
soldier.executeCmd(cmd);
}
}
}
//命令执行者
class Soldier {
public void executeCmd(Command cmd) {
cmd.execute();
}
}