之前一直想了解关于设计模式相关内容,看了何红辉 大神的 《Android 源码设计模式解析与实战》 一书的部分章节,感觉写的很好。正巧最近在进行代码重构,加上 RecycleView 系列下篇文章的 demo 想结合一下设计模式,于是重读这本书,并简单记录一下,加深印象。
首先先大致了解下都有哪些设计模式。
按照模式的应用目标分类,设计模式可以分为创建型模式、结构型模式和行为型模式。
创建型模式 ,是对对象创建过程的各种问题和解决方案的总结。
包括:各种工厂模式(Factory、Abstract Factory)、单例模式(Singleton)、构建器模式(Builder)、原型模式(ProtoType)
结构型模式,关注于类、对象继承、组合方式。
常见的有:桥接模式(Bridge)、适配器模式(Adapter)、装饰者模式(Decorator)、代理模式(Proxy)、组合模式(Composite)、外观模式(Facade)、享元模式(Flyweight)
行为型模式,从类或对象间交互、职责划分等角度总结的模式。
常见的有:策略模式(Strategy)、解释器模式(Interpreter)、命令模式(Command)、观察者模式(Observer)、迭代器模式(Iterator)、模板方法模式(Template Method)、访问者模式(Visitor)
下面来看一下工厂方法模式
工厂方法模式(Factory Pattern),是创建型设计模式之一。根据上面总结的,我们知道肯定是跟对象的创建有关。
定义:定义一个用于创建对象的接口,让子类决定实例化哪个类。
需要生成复杂对象的地方。
用 new 就可以完成创建的对象不需要使用。
举个小例子,前些天看了夏目友人帐剧场版,其中猫咪老师变成了三个,那我假设树洞是个工厂(哈哈哈),然后生产出猫咪老师一号、二号和三号这三个产品。
按照上面的几大角色,首先我们写下我们最终需要生产出的猫咪老师(具体产品,一号、二号和三号 ) 的抽象特征(喝酒),即抽象产品这一角色:
/**
* 所有生产出的猫咪老师的抽象方法
*/
public abstract class Sansan {
/**
* 抽象方法,喝酒
*/
public abstract void drink();
}
然后,我们要生产出1号、2号和3号,即具体产品这一角色:
/**
* 猫咪老师 1 号
*/
public class SansanNo1 extends Sansan{
@Override
public void drink() {
System.out.println(" Hello! Im sansan No.1,I want to drink\n");
}
}
/**
* 猫咪老师 2 号
*/
public class SansanNo2 extends Sansan{
@Override
public void drink() {
System.out.println(" Hello! Im sansan No.2,I want to drink\n");
}
}
/**
* 猫咪老师 3 号
*/
public class SansanNo3 extends Sansan{
@Override
public void drink() {
System.out.println(" Hello! Im sansan No.3,I want to drink\n");
}
}
接着,看一下抽象工厂:
/**
* 抽象工厂类,树洞
*/
public abstract class SanSanFactoty {
/**
* 抽象工厂方法,具体生产什么让子类去实现
* @return sansan猫咪老师
*/
public abstract Sansan createSansan();
}
有了抽象工厂,让我们来实现具体工厂,来生产具体类型的产品:
/**
* 具体工厂方法,用来决定生产哪一个产品(猫咪老师)
*/
public class CreateSansanFactory extends SanSanFactoty {
/**
* 生产猫咪老师
* @return 具体类型的猫咪老师
*/
@Override
public Sansan createSansan() {
// return new SansanNo1();
// return new SansanNo2();
return new SansanNo3();
}
}
在需要调用的类里面这样调用:
public static void factoryTest(){
SanSanFactoty factory = new CreateSansanFactory();
Sansan sansan = factory.createSansan();
sansan.drink();
}
这种比较简单,需要哪个就生产哪个,但是需要改动具体工厂的类。
有时可以利用反射的方式更简洁的来生产具体产品对象,这时需要在工厂方法的参数列表里传入一个 class 类来决定是哪一个产品类。可以如下改动:
/**
* 抽象工厂类,树洞
*/
public abstract class SanSanFactoty {
/**
* 抽象工厂方法,具体生产什么让子类去实现
* @param clz 产品对象类类型
* @return 具体的产品对象
*/
public abstract T createSansan(Class clz);
}
/**
* 具体工厂方法,用来决定生产哪一个产品(猫咪老师)
*/
public class CreateSansanFactory extends SanSanFactoty {
@Override
public T createSansan(Class clz) {
Sansan sansan = null;
try {
sansan = (Sansan) Class.forName(clz.getName()).newInstance();
}catch (Exception e){
e.printStackTrace();
}
return (T) sansan;
}
}
需要调用的类改写为:
public static void factoryTest(){
SanSanFactoty factory = new CreateSansanFactory();
//Sansan sansan = factory.createSansan(SansanNo1.class);
Sansan sansan = factory.createSansan(SansanNo2.class);
sansan.drink();
}