任何设计模式都是为了解决某些特定场景下所遇到的问题,要知道设计模式其实是可以有一些变动的,说白了设计模式是一种思想而并非一种代码,不要为了使用某种模式生搬硬套。当我们理解一种设计模式的思想时,不要去钻牛角尖。我们在开发中遇到一些问题的时候,就可以在脑海中翻一翻我们所积攒的知识,是不是可以用某一些设计模式来解决这个问题,又或者是用其他方式来解决。当然我们也需要去看一些文章和书籍,很多都写得非常不错,但是我们不能只了解书中所说的例子如: 小轿车的创建过程,电脑的组装,银行办理业务等等,更多需要花时间去思考,怎样用我们自己的项目框架中,否则看过了大量的文章和书籍,发现好像知道那么回事,但就是项目中不知道怎么用。思想要打通,但实战更为重要。
1.问题思考
仍记得去年刚到公司那会,跟着大家伙一起工作,那时公司已有 7 个人在做 android 开发,我也不知道整个项目写得怎样,我看了大部分代码,发现很多有问题,其中保存用户信息是这么写的:
ACache mCache = ACache.get(this);
mCache.put("userName", "darren");
mCache.put("userHeader", "http://www.xxxxx.jpg");
当时看到这个代码我就在想后面肯定会有问题,先不说没有用 LoginSession 去管理,单拿数据的存储来说,这样直接写肯定是有问题的。因为今天的主要内容讲的是讲工厂设计模式,这里我就不说与 LoginSession 相关的内容,也不说这个框架 ASimpleCache 怎么样,今天特意查了一下有 2000+ 的star。果不其然后面快要上线的时候,因为当时由于清理缓存的功能,需要清理某一部分数据,但是部分数据(用户信息)是需要保留的,当我们调用 clear 的方法是全部清理。这个时候摆在我们面前的解决方法有很多,第一种,干脆就不做清理只是做一个假数据的显示和 Toast ;第二种,把用户信息用另一种缓存存着;第三种,就是把 ASimpleCache 的依赖删除,统统改掉。第一种可能是最快的方式,第三种是最慢的,后来经过商量之后还是决定全部改掉,并且由我来改采用第三种方式。好在当时只有 20+ 的地方用了,大概改了一个小时就改好了,把依赖去掉,哪里报错改哪里。当我们碰到这个问题的时候,我想应该不是立马去解决问题,就像我文章开头所说的一样,而是想避免下次再出现这样的问题,今天我们就用工厂设计模式,看下数据存储应该怎么存。
2.工厂设计模式介绍
2.1 模式定义
定义一个创建对象的接口,让子类决定实例化哪个类,而对象的创建统一交由工厂去生成,既做到了解耦也保证了最少知识原则。一般分为三类:简单工厂模式,工厂方法模式,抽象工厂模式
2.2 简单工厂模式
目前按照数据的存储我们一般是有这么几类,内存,SharedPreferences,数据库,磁盘,存储的数据一般分为基本数据类型和对象,先上 UML 图
public class IOFactory implements Factory{
// 通过 Factory 去创建 IOHandler 对象
public static IOHandler createIOHandler(IOType type){
switch (type){
case IOType.MEMORY:
// 内存缓存
return new MemoryIOHandler();
case IOType.PREFERENCES:
// Preferences缓存
return new PreferencesIOHandler();
case IOType.DISK:
// 磁盘缓存
return new DiskIOHandler();
default:
return null;
}
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取磁盘缓存的 IOHandler
IOHandler ioHandler = IOFactory.createIOHandler(IOFactory.IOType.DISK);
// 保存数据
ioHandler.save("userName","darren");
ioHandler.save("userPwd","940223");
}
public void click(View view){
// 获取磁盘缓存的 IOHandler
IOHandler ioHandler = IOFactory.createIOHandler(IOFactory.IOType.DISK);
// 获取数据
String userName = ioHandler.getString("userName");
String userPwd = ioHandler.getString("userPwd");
Log.e("TAG","userName = "+userName+" userPwd = "+userPwd);
}
}
上面就是我们的简单工厂模式,就这么简单,可以看到我们不是直接通过 new 对象来保存数据的,而是用不同的类型,通过 IOFactory 去创建我们的对象。这样目前来讲也看不出什么好处,而且问题还是有很多。
2.3 工厂方法模式
IOFactory 掌管了所有的业务逻辑处理。这样的类,我们称为上帝类/全能类。上帝类耦合度非常高,每当需要增加一种缓存是,就需要大量更改 IOFactory 中的代码,而且也不符合开闭原则,比如我想加一个 DatabaseIOHandler 等等。接下来看下工厂方法模式, 先上 UML 图
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建 IOFactory 生成 IOHandler
DiskIOFactory diskIOFactory = new DiskIOFactory();
IOHandler ioHandler = diskIOFactory.createIOHandler();
// 保存数据
ioHandler.save("userName","darren");
ioHandler.save("userPwd","940223");
}
public void click(View view){
// 创建 IOFactory 生成 IOHandler
DiskIOFactory diskIOFactory = new DiskIOFactory();
IOHandler ioHandler = diskIOFactory.createIOHandler();
// 获取数据
String userName = ioHandler.getString("userName");
String userPwd = ioHandler.getString("userPwd");
Log.e("TAG","userName = "+userName+" userPwd = "+userPwd);
}
}
工厂方法模式也是很好理解的,这个时候我们想增加 DatabaseIOHandler 就只需要新增 DatabaseIOFactory 创建一个 DatabaseIOHandler 就行了,而不是去修改我们原来的代码。但是随着数据存储方式的增加,相应的工厂类也会同比增加,造成项目文件十分臃肿巨大。我们可能也需要好好考虑,到底要不要用,于是为了减少工厂类的出现数量,抽象工厂模式诞生了。
2.4抽象工厂模式
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取默认的 IOHandler , 默认是磁盘存储
IOHandler ioHandler = IOFactory.getFactory().getDefaultIOHandler();
// 保存数据
ioHandler.save("userName","darren");
ioHandler.save("userPwd","940223");
}
public void click(View view){
// 获取默认的 IOHandler , 默认是磁盘存储
IOHandler ioHandler = IOFactory.getFactory().getDefaultIOHandler();
// 获取数据
String userName = ioHandler.getString("userName");
String userPwd = ioHandler.getString("userPwd");
Log.e("TAG","userName = "+userName+" userPwd = "+userPwd);
}
}
最近有很多认识的哥们在找工作,都说感觉不是很好找,很多哥们都给我看了简历,换工作之前要想好准备好,骑驴找马等等这里先不说,单拿我看的简历来讲,简历一定要有突出的亮点,比如你会用 RXjava+OKhttp+Retrofit 来做项目,我想很多人都会用,如果你能知道原理这就算是一个亮点,而面试的时候我一般也会问一些这方面的内容,又或者你看过大量的 FrameWorker 层的源码,读过大公司的一些开源框架像阿里腾讯的热修复源码,360和滴滴的插件化开发源码等等,当然最好是去读最新版的,这些都算是亮点。
所有分享大纲:Android进阶之旅 - 系统架构篇