CSDN是我用过的最垃圾的东西
工厂方法模式 - 应用最广泛的模式
###1.介绍:工厂方法模式(Factory Pattern)是创建型设计模式之一。工厂方法模式是一种 结构简单的模式。
###2.定义:定义一个用于创建 对象的接口,让子类决定实例化哪个类。
###3.使用场景:在任何需要生成复杂对象的地方,都可以使用工厂方法模式。复杂对象适合使用工厂模式,用new 就可以完成创建的对象无需使用工厂模式。
###4.:栗子和分析
-
举个栗子:工厂模式的通用模式代码
public abstract class Product {
/**
* 产品类的抽象方法
* 由具体的产品类来实现
*/
public abstract void method();
}public class ConcreteProductA extends Product{
@Override
public void method() {
System.out.println(“这是具体的产品A”);
}
}
public class ConcreteProductB extends Product{
@Override
public void method() {
System.out.println(“这是具体的产品B”);
}
}
public abstract class Factory {
/**
* 抽象工厂方法
* 具体生产的产品由子类去实现
/
public abstract Product createProduct();
}
/*- 具体的工厂实现类
/
public class ConcreteFactory extends Factory{
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
/* - 客户类
*/
public class Client {
public static void main(String[] args) {
Factory factory = new ConcreteFactory();
Product product = factory.createProduct();
product.method();
}
}
- 具体的工厂实现类
-
1.代码分析:ConcreteProductA,和ConcreteProductB继承了抽象类Product,并重写了父类的抽象方法,method。
-
2.ConcreteFactory类继承了抽象类Factory并且重写了父类的createProduct方法:返回一个创建了的CocreteProductA对象。
-
3.Client类,在该类的main方法中,创建了ConcreteFactory对象,并且通过调用ta的createProduct方法,获取了Product对象(实际是ConcreteProductA对象),接着该product对象调用ta的method方法:在console上输出打印的message。
-
模式分析:这里的几个角色都很简单,主要分为四个模块,
-
一是抽象工厂,这是工厂模式核心
-
二是具体工厂,实现具体的业务逻辑
-
三是抽象产品,是工厂方法模式所创建的产品的父类
-
四是具体产品,为实现抽象产品的某个具体产品的对象
-
以上就是工厂模式的四个重要组成部分。
-
上述的代码中在Client类中构造了一个工厂对象,同工作其生产了一个产品对象,这里获取而是ConcreteProductA对象的实例;如果想得到ConcreteProductB对象只需更改createProduct方法的返回对象即可。
-
这种方式很简单,需要哪一个产品就生产哪一个。
-
更简洁的生产具体对象的方法:反射。此时需要在工厂方法的参数列表中传入一个Clss类来决定是哪个产品类。具体代码如下咯:
public abstract class Factory2 {
/**
* 抽象工厂方法
* 具体生产什么由子类去实现
/
public abstract T createProduct(Class clz);
}
public class ConcreteFactory2 extends Factory2{
/*
*
* @param clz 产品对象的类型
* @param 泛型
* @return 具体的产品对象
/
@Override
public T createProduct(Class clz) {
Product product = null;
try {
product = (Product) Class.forName(clz.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) product;
}
}
public class Client2 {
/*
*
* @param args
*/
public static void main(String[] args) {
Factory2 factory2 = new ConcreteFactory2();
ConcreteProductB productB = factory2.createProduct(ConcreteProductB.class);
productB.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 {
public static void main(String[] args) {
Factory factoryA = new ConcreteFactoryA();
Product productA = factoryA.createProduct();
productA.method();
Factory factoryB = new ConcreteFactoryB();
Product productB = factoryA.createProduct();
productB.method();
}
} -
像这种拥有多个工厂的方式我们称为多工厂方法模式,**同样地,回到我们最初的那个工厂模式,当我们的工厂只有一个的时候,我们还是为工厂模式提供了一个抽象类,那么我们是否可以将其简化掉呢?**如果确定你的工厂类中只有一个,那么简化掉抽象类肯定是没问题的:我们只需要将对应的工厂方法改为静态方法即可。如下:
public class Factory {
public static Product createProduct() {
return new ConcreteProductA();
}
} -
像这样的方式又称为简单工厂模式,它是工厂方法模式的一个弱化版本。工厂方法模式是完全符合设计原则的:降低了对象之间的耦合度,而且,工厂方法模式依赖于抽象的架构,其将实例化的任务交给子类去完成,有非常好的可拓展性。
模式的简单实现
- 现在,需要生产某款suv的三种车型,例如Q3,Q5,Q7,对于这类车型而言,内部结构差役并不是很大,因此一种生产线就可以应付这三种车型,下面是该生产线的抽象类定义
public abstract class AudiFactory {
/**
*
* @param clz 具体的SUV型号
* @param 泛型
* @return 具体型号的SUV车对象
*/
public abstract T createAudiCar(Class clz);
}
-
因为这三种suv在主结构上并没有什么差异,所以没有必要对每中车型都提供一条不同的生产线,一条生产线就可以了。
public class AudiCarFactory extends AudiFactory{
@Override
public T createAudiCar(Class clz) {
AudiCar audiCar = null;
try {
audiCar = (AudiCar) Class.forName(clz.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) audiCar;
}
} -
对于这三种车型呢,除了一些车都有的基本功能外,还提供了自动驾驶功能:这些功能都使用一个抽象的基类来声明
public abstract class AudiCar {
/**
* 驾驶的功能
/
public abstract void drive();
/*
* 汽车的抽象产品类
* 定义汽车的一个行为方法:自动驾驶
*/
public abstract void selfNavigation();
} -
家下来就是生产每一种具体的车型:
public class AudiQ3 extends AudiCar{
@Override
public void drive() {
System.out.println(“AudiQ3开始启动上路啦”);
}
@Override
public void selfNavigation() {
System.out.println(“AudiQ3开始自动驾驶啦”);
}
}
public class AudiQ5 extends AudiCar{
@Override
public void drive() {
System.out.println(“AudiQ5开始启动上路啦”);
}
@Override
public void selfNavigation() {
System.out.println(“AudiQ5开始自动驾驶啦”);
}
}
public class AudiQ7 extends AudiCar{
@Override
public void drive() {
System.out.println(“AudiQ7开始启动上路啦”);
}
@Override
public void selfNavigation() {
System.out.println(“AudiQ7开始自动驾驶啦”);
}
} -
最后我们将各个部分组装起来,完成生产线的功能
public class Client {
public static void main(String[] args) {
AudiCarFactory factory = new AudiCarFactory();
AudiQ3 audiQ3 = factory.createAudiCar(AudiQ3.class);
audiQ3.drive();
audiQ3.selfNavigation();
AudiQ5 audiQ5 = factory.createAudiCar(AudiQ5.class);
audiQ5.drive();
audiQ5.selfNavigation();
AudiQ7 audiQ7 = factory.createAudiCar(AudiQ7.class);
audiQ7.drive();
audiQ7.selfNavigation();
}
} -
以上代码结构简单,逻辑也类似,很容易理解的。
###6.Android 源码中工厂方法模式的实现
-
工厂方法模式的应用很广发,大家平时开发过程中经常会使用到数据结构中其实就有对工厂模式的应用:List和Set,List和Set都继承与Collection接口,而Collection接口继承与Iterable接口,Iterable接口很简单,就一个iterator方法。
public inteface Iterable{
Iterator iterator();
} -
这意味着List和Set也会继承该方法,平时比较常用的两个间接实现类Arraylist和HashSet中iterator烦恼歌发的实现就是构造并返回一个迭代器对象。 page - 93.
-
Arraylist 源码
/**
* Returns an iterator over the elements in this list in proper sequence.
*
*The returned iterator is fail-fast.
*
* @return an iterator over the elements in this list in proper sequence
/
public Iterator iterator() {
return new Itr();
}
/*
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings(“unchecked”)
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings(“unchecked”)
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
} -
HashSet源码
/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set
* @see ConcurrentModificationException
*/
public Iterator iterator() {
return map.keySet().iterator();
} -
HashSet的iterator方法中会返回成员变量 backingMap中对应HashSet对象元素的迭代器对象,最终返回的是KeySet中的一个迭代器对象。
-
分析:ArrayList和HasetSet中的iterator方法其实就相当有一个工厂方法,专为new 对象而存在。这里iterator方法是构造并返回一个具体的迭代器
-
*Android中工厂方法模式的应用
public class XxActivity extends Activity{
@override
protected void onCreate(Bundle savedInstanceState){
super.Oncreate(savedInstanceState);
setContentView(new LinearLayout(this));
}
} -
分析:这里构造一个线性布局LinearLayout对象并且设置为当前Activity的根布局,这段代码看似简单不过,其实这就相当于一个工厂方法,为什么呢?:LinearLayout 是一个viewGroup,ViewGroup继承自View,简单的说,所有的控件都是View的子类。在上面的代码中我们在XxActivity的onCreate方法中构造一个View对象,并设置为当前界面ContentView并返回给framework处理,如果现在又有一个XyActivity,这时又可以通过setContentView方法设置不同的View。可知:这就是一个工厂方法模式的结构!
###7.关于onCreate方法
8.工厂方法模式实战
- 重要组成部分:
- 1.抽象的product类
- 2.具体的product类
- 3,factory类(根据传入的product类,产生对应的对象)
- 代码就不贴了
###9.总结
- 工厂方法模式是很好的设计模式,它的有优点是具有很好的拓展性;它的缺点也是难以避免的,每次我们为工厂方法模式添加新的产品时就要编写一个新的产品类,同时还要引入抽象层,这就必然会导致类结构的复杂化,所以在某些情况比较简单时,是否使用该模式,需要细细权衡。