设计模式之工厂方法模式
一、工厂方法模式介绍
工厂方法模式(Factory Pattern)是创建型设计模式之一,是一种结构简单的模式,在我们平时开发中应用很广泛。
二、工厂方法模式的定义
定义一个用于创建对象的接口,让子类决定实例化哪个类。
三、工厂方法模式的使用场景
在任何需要生成复杂对象的地方,都可以使用工厂方法模式。复杂对象适合使用工厂模式,用new就可以完成创建的对象无需使用工厂模式。
四、工厂方法模式的UML类图
五、工厂方法模式的简单实现
根据上图,我们可以得出下一个工厂方法模式的通用模式代码。
/**
* 抽象产品类
*
* @author chenyongliang
* @time 2018/1/12 上午11:36
*/
public abstract class Product {
/**
* 产品类的抽象方法,由具体的产品类去实现
*/
public abstract void method();
}
/**
* 具体产品类A
*
* @author chenyongliang
* @time 2018/1/12 上午11:40
*/
public class ConcreteProductA extends Product {
@Override
public void method() {
Log.e("","ConcreteProductA-我是具体的产品A");
}
}
/**
* 具体产品类B
*
* @author chenyongliang
* @time 2018/1/12 上午11:40
*/
public class ConcreteProductB extends Product {
@Override
public void method() {
System.out.print("ConcreteProductB-我是具体的产品B");
Log.e("","ConcreteProductB-我是具体的产品B");
}
}
/**
* 抽象工厂类
*
* @author chenyongliang
* @time 2018/1/12 上午11:42
*/
public abstract class Factory {
/**
* 抽象工厂方法
* 具体生产什么由子类去实现
*
* @return 具体的产品对象
*/
public abstract Product createProduct();
}
/**
* 具体工厂类
*
* @author chenyongliang
* @time 2018/1/12 上午11:47
*/
public class ConcreteFactory extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
//客户类
public class Client extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Factory factory = new ConcreteFactory();
Product product = factory.createProduct();
product.method();
}
}
这里的几个角色主要分为四大模块:
1、抽象工厂:为工厂方法模式的核心;
2、具体工厂:实现了具体的业务逻辑;
3、抽象产品:工厂方法模式所创建的产品的父类;
4、具体产品:为实现抽象产品的某个具体产品的对象。
在上述代码中我们在Client类中构造了一个工厂对象,并通过其产生了一个产品对象,这里我们得到的产品对象是ConcreteProductA的实例,如果想得到ConcreteProductB的实例,更改ConcreteFactory中的逻辑即可:
/**
* 具体工厂类
*
* @author chenyongliang
* @time 2018/1/12 上午11:47
*/
public class ConcreteFactory extends Factory {
@Override
public Product createProduct() {
// return new ConcreteProductA();
return new ConcreteProductB();
}
}
这种方式比较常见,需要哪一个产品就生产哪一个,有时候也可以利用反射的方式更简洁地来生产具体产品对象,此时,需要再工厂方法的参数列表中传入一个Class类来决定是哪一个产品类:
public abstract class Factory {
/**
* 抽象工厂方法
* 具体生产什么由子类去实现
*
* @param clz 产品对象类类型
* @param <T>
* @return 具体的产品对象
*/
public abstract<T extends Product> T createProduct(Class<T> clz);
}
对于具体的工厂类,则通过反射获取类的示例即可:
public class ConcreteFactory extends Factory {
@Override
public <T extends Product> T createProduct(Class<T> clz) {
Product p = null;
try {
p = (Product) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) p;
}
}
最后再来看看Client中的实现
public class Client extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Factory factory = new ConcreteFactory();
Product product = factory.createProduct(ConcreteProductB.class);
product.method();
}
}
需要哪一个类的对象就传入哪一个类的类型即可,这种方法比较简洁,动态,如果不喜欢这种方式,也可以尝试为每一个产品都定义一个具体的工厂,各司其职:
public class ConcreteFactoryA extends Factory{
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
public class ConcreteFactoryB extends Factory{
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
public class Client extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Factory1 factory = new ConcreteFactory();
// Product product = factory.createProduct(ConcreteProductB.class);
// product.method();
Factory factoryA = new ConcreteFactoryA();//具体工厂A
Product productA = factoryA.createProduct();//具体产品A
productA.method();
Factory factoryB = new ConcreteFactoryB();//具体工厂B
Product productB = factoryB.createProduct();//具体产品B
productB.method();
}
}
像这样拥有多个工厂的方式我们称之为多工厂方法模式,同样地,回到我们最初的那个工厂方法模式,当我们的工厂只有一个的时候,我们还是为工厂提供了一个抽象类,那么,我们是否可以将其简化掉呢?
如果确定你的工厂类只有一个,那么简化掉抽象类是肯定没问题的。我们只需要将对应的工厂方法给为静态方法即可:
public class Factory_ {
public static Product createProduct() {
// return new ConcreteProductA();
return new ConcreteProductA();
}
}
像这样的方式又称之为简单工厂模式或静态工厂模式,它是工厂方法模式的一个弱化版本。
其实这里大家应该可以发现,工厂方法模式是完全符合设计原则的,其降低了对象之间的耦合度,而且,工厂方法模式依赖于抽象的架构,其将实例化的任务交由子类去完成,有非常好的扩展性。
以生产汽车为例工厂模式的简单实例:
/**
* Created by chenyongliang on 2018/1/12.
*/
public abstract class AudiFactory {
/**
* 某车型的工厂方法
*
* @param clz 具体的SUV型号类型
* @param <T>
* @return 具体型号的SUV车对象
*/
public abstract <T extends AudiCar> T createAudiCar(Class<T> clz);
}
那么有没有必要为每种车型都提供一条生产线呢?这里生产的几种SUV车型可能在主结构上并没有什么差异,因此没有必要为每一种车型都提供一条不同的生产线,一条生产线即可:
public class AudiCarFactory extends AudiFactory {
@Override
public <T extends AudiCar> T createAudiCar(Class<T> clz) {
AudiCar car = null;
try {
car = (AudiCar) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) car;
}
}
对于这类SUV车型,除了一些车都有的基本共性外,还提供了自动巡航功能,类似于无人驾驶,这些功能都用一个抽象的基类来声明:
public abstract class AudiCar {
/**
* 汽车的抽象产品类
* <p>
* 定义汽车的一个行为方法 车可以启动开走
*/
public abstract void drive();
/**
* 汽车的抽象产品类
* <p>
* 定义汽车的一个行为方法 车可以自动巡航
*/
public abstract void selfNavigation();
}
接下来就是生产每一种具体的车型了:
public class AudiQ3 extends AudiCar {
@Override
public void drive() {
System.out.println("Q3 启动啦!");
}
@Override
public void selfNavigation() {
System.out.println("Q3 开始自动巡航啦!");
}
}
public class AudiQ5 extends AudiCar {
@Override
public void drive() {
System.out.println("Q5 启动啦!");
}
@Override
public void selfNavigation() {
System.out.println("Q5 开始自动巡航啦!");
}
}
public class AudiQ7 extends AudiCar {
@Override
public void drive() {
System.out.println("Q7 启动啦!");
}
@Override
public void selfNavigation() {
System.out.println("Q7 开始自动巡航啦!");
}
}
最后我们将各个类组装起来形成一条完整的流水线:
public class Client extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//构造一个制造汽车的工厂对象
AudiFactory factory = new AudiCarFactory();
//生产Q3 并启动
AudiQ3 audiQ3 = factory.createAudiCar(AudiQ3.class);
audiQ3.drive();
audiQ3.selfNavigation();
//生产Q5 并启动
AudiQ5 audiQ5 = factory.createAudiCar(AudiQ5.class);
audiQ5.drive();
audiQ5.selfNavigation();
//生产Q7 并启动
AudiQ7 audiQ7 = factory.createAudiCar(AudiQ7.class);
audiQ7.drive();
audiQ7.selfNavigation();
}
}
输出结果如下:
由上述可以看到,工厂方法模式的结构很简单,逻辑也基本类似,所有,上面例子与我们类图中所述的结构是很类似的。
六、Android源码中的工厂方法模式实现
工厂方法模式应用很广泛,大家平时开发中经常会使用到的数据结构中其实也影藏这对工厂方法模式的应用
以List和Set为例,List 和 Set 都继承于Collection接口,而Collection接口继承于Iterable接口,Iterable接口很简单,就一个iterator方法:
public interface Iterable<T> {
Iterator<T> iterator();
}
这意味着List 和 Set接口也会继承该方法,平时比较常用的两个间接实现类 ArrayList 和 HashSet 中 iterator 方法的实现就是构造并返回一个迭代器对象.
……..