抽象方法模式 java_五:抽象方法模式

五:抽象方法模式

抽象工厂模式算是工厂相关模式的终极形态,如果各位完全理解了上一章的工厂方法模式,那么抽象工厂模式就很好理解了。它与工厂方法唯一的区别就是工厂的接口里是一系列创造抽象产品的方法...

抽象工厂模式算是工厂相关模式的终极形态,如果各位完全理解了上一章的工厂方法模式,那么抽象工厂模式就很好理解了。它与工厂方法唯一的区别就是工厂的接口里是一系列创造抽象产品的方法,而不再是一个,而相应的,抽象产品也不再是一个了,而是一系列相关的产品。这其实是工厂方法模式的一种扩展不是吗?

通常意义来我们谈到扩展,通常有两种方式可以扩展一个接口或者类,就是继承和组合。

通常情况下,我们推荐使用组合扩展一个现有的类或接口,但这并非绝对,如果你扩展的子类或子接口与现有的类或接口明显是“是一个(is a)”的关系,也就是继承的关系,那么使用继承可以获得更多的好处。

下面我们就首先来看一下抽象工厂模式的定义以及类图,全部引自百度百科。

定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

定义中说了,我们是要创建一个接口, 而这个接口是干嘛的呢,前面说了,是为了创建一组相关或者相互依赖的对象,而且还有一点就是,我们创建的对象不是具体的类,也就是说我们创建的是一个接口或者一个抽象类。

下面我们来看看抽象工厂模式的类图。

b17420c7b1c780e6c3e7543be3046ca1.jpg

package net;

interface ProductA {

void methodA();

}

interface ProductB {

void methodB();

}

class ProductA1 implements ProductA{

public void methodA() {

System.out.println("产品A系列中1型号产品的方法");

}

}

class ProductA2 implements ProductA{

public void methodA() {

System.out.println("产品A系列中2型号产品的方法");

}

}

class ProductB1 implements ProductB{

public void methodB() {

System.out.println("产品B系列中1型号产品的方法");

}

}

class ProductB2 implements ProductB{

public void methodB() {

System.out.println("产品B系列中2型号产品的方法");

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

结构比较清晰,下面是类图中左半部分,首先给出工厂接口。

48304ba5e6f9fe08f3fa1abda7d326ab.png

package net;

public interface Creator {

ProductA createProductA();

ProductB createProductB();

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

下面是两个具体的工厂实现类。

48304ba5e6f9fe08f3fa1abda7d326ab.png

package net;

public class ConcreteCreator1 implements Creator{

public ProductA createProductA() {

return new ProductA1();

}

public ProductB createProductB() {

return new ProductB1();

}

}

package net;

public class ConcreteCreator2 implements Creator{

public ProductA createProductA() {

return new ProductA2();

}

public ProductB createProductB() {

return new ProductB2();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

这样我们的类图代码就实现完毕,下面我们写一个测试类,去调用一下,感受一下抽象工厂模式的客户端调用方式。

48304ba5e6f9fe08f3fa1abda7d326ab.png

package net;

public class Client {

public static void main(String[] args) throws Exception {

Creator creator = new ConcreteCreator1();

ProductA productA = creator.createProductA();

ProductB productB = creator.createProductB();

productA.methodA();

productB.methodB();

creator = new ConcreteCreator2();

productA = creator.createProductA();

productB = creator.createProductB();

productA.methodA();

productB.methodB();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

在过程当中,我们切换过一次工厂实现类,而下面的代码是一模一样的,但是我们使用的就是另一套产品实现体系了,我们看运行结果。

b8706137511febb60deeef22f9e75bc2.jpg

package java.util;

public interface List extends Collection {

Iterator iterator();//一种产品

Object[] toArray();

T[] toArray(T[] a);

ListIterator listIterator();//另外一种产品

ListIterator listIterator(int index);

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

LZ去掉了List接口中的很多方法,一是为了节省版面,另外是为了更清晰,我们主要关注iterator和listIterator方法,LZ在上面加了标注。

其中ListIterator是Iterator的子接口,但归根到底,它其实属于另外一种产品,为什么这么说呢,ListIterator不是Iterator的子接口吗,怎么能算是另外一种产品呢?这是因为我们listIterator方法的返回类型是ListIterator,而不是Iterator,所以两者的功能是不同的,比如ListIterator还可以向前移动。

我们可以认为这两个方法产生的一个是只能向后移动的迭代器,一个是可以前后移动的迭代器,这算是两种产品,相当于上面的ProductA和ProductB。

这个设计可以看做是一个抽象工厂模式,List接口定义了两种生产不同产品的方法,这属于两个系列的产品,不过由于产品接口本身的继承关系,两者的实现类也会被做成继承的关系。下面给出上面提到的接口的UML图。

d183e21bcfbf352e312aa806c1eedce4.jpg

//抽象产品

interface Product{}

//具体产品

class ProductA implements Product{}

class ProductB implements Product{}

//产品工厂(下一步就是它的进化,就变成了工厂方法模式)

public class ProductFactory {

private ProductFactory(){}

public static Product getProduct(String productName){

if (productName.equals("A")) {

return new ProductA();

}else if (productName.equals("B")) {

return new ProductB();

}else {

return null;

}

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

LZ在上面加了简单的注释,下面LZ给出工厂方法模式的代码,注意,前面有关产品的类和接口是不变的。

48304ba5e6f9fe08f3fa1abda7d326ab.png

//抽象产品

interface Product{}

//具体产品

class ProductA implements Product{}

class ProductB implements Product{}

//将简单工厂中的工厂给抽象成接口

interface Factory{

Product getProduct();

}

//具体的工厂A,创造产品A

class FactoryA implements Factory{

public Product getProduct() {

return new ProductA();

}

}

//具体的工厂B,创造产品B

class FactoryB implements Factory{

public Product getProduct() {

return new ProductB();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

可以看到,产品部分并没有变化,只是将简单工厂中的工厂类抽象成接口,并给相应产品添加相应的工厂类,就进化成了工厂方法模式。下面我们再看工厂方法如何进化成抽象工厂模式。

48304ba5e6f9fe08f3fa1abda7d326ab.png

//抽象产品

interface Product{}

//具体产品

class ProductA implements Product{}

class ProductB implements Product{}

//多了一个抽象产品1

interface Product1{}

//具体产品1

class Product1A implements Product1{}

class Product1B implements Product1{}

//原有的工厂方法模式的工厂里添加一个方法

interface Factory{

Product getProduct();

//添加另外一个产品族的创造方法

Product1 getProduct1();

}

//具体的工厂A,创造产品A

class FactoryA implements Factory{

public Product getProduct() {

return new ProductA();

}

//添加相应的实现

public Product1 getProduct1() {

return new Product1A();

}

}

//具体的工厂B,创造产品B

class FactoryB implements Factory{

public Product getProduct() {

return new ProductB();

}

//添加相应的实现

public Product1 getProduct1() {

return new Product1B();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

与工厂方法对比下就发现,多了一个产品系列叫Product1,工厂接口里多了一个方法,叫getProduct1,所以抽象工厂模式就是工厂方法模式添加了抽象产品所演变而来的。

有关工厂的三个模式到这里就全部介绍完了,三者有着很大的关联和明显的关系,要想灵活运用这三种设计模式,还是要彻底理解它们所针对的问题以及三者的关系。下面罗列下这三种设计模式依次进化的原因。

1,首先从简单工厂进化到工厂方法,是因为工厂方法弥补了简单工厂对修改开放的弊端,即简单工厂违背了开闭原则。

2,从工厂方法进化到抽象工厂,是因为抽象工厂弥补了工厂方法只能创造一个系列的产品的弊端。

各位可以思考下,假设我们不使用抽象工厂模式,改用工厂方法去处理抽象工厂中多产品的问题,如何处理呢?其实很简单,就是有几个产品系列,我们就造几个工厂方法模式就可以了,只不过这样处理未免太不优雅,就像下面这样。

48304ba5e6f9fe08f3fa1abda7d326ab.png

//抽象产品

interface Product{}

//具体产品

class ProductA implements Product{}

class ProductB implements Product{}

//工厂接口

interface Factory{

Product getProduct();

}

//具体的工厂A,创造产品A

class FactoryA implements Factory{

public Product getProduct() {

return new ProductA();

}

}

//具体的工厂B,创造产品B

class FactoryB implements Factory{

public Product getProduct() {

return new ProductB();

}

}

/* 以上是一个产品的工厂方法 */

//抽象产品1

interface Product1{}

//具体产品1

class Product1A implements Product1{}

class Product1B implements Product1{}

//工厂接口1

interface Factory1{

Product1 getProduct1();

}

//具体的工厂1A,创造产品1A

class Factory1A implements Factory1{

public Product1 getProduct1() {

return new Product1A();

}

}

//具体的工厂1B,创造产品1B

class Factory1B implements Factory1{

public Product1 getProduct1() {

return new Product1B();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

以上用两个工厂方法模式,代替了抽象工厂模式,那么可想而知,假设又多了一个产品Product2,那么我们还需要再建立一套工厂方法模式,这显然会大大增加系统的复杂性,而且也不易于客户端操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值