JAVA设计模式之抽象工厂(Abstract Factory)模式

在阅读本篇以前,为了方便理解,请首先阅读本博的“JAVA设计模式之简单工厂(Simple Factory)模式”和“JAVA设计模式之工厂方法(Factory Method)模式”。

抽象工厂模式是对象的创建模式,它是工厂方法模式的进一步推广。抽象工厂的“抽象”来自于“抽象的产品角色”,而抽象工厂就是抽象产品角色的工厂。每一个设计模式都是针对一系列的问题的解决方案。抽象模式就是针对多个等级产品结构的系统而设计的。抽象工厂模式就是向客户端提供一个接口,使得客户端在不必知道产品的具体类型的情况下,创建多个产品族中的产品。

抽象工厂中的各个角色又是怎么样的呢?

抽象工厂(Abstract Factory)角色:该角色是工厂方法模式的核心,它是以应用程序无关的。它往往由接口或抽象类来实现。所有的具体工厂类都应该实现这个Java接口或是继承这个Java类。

具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑与系统的商业逻辑紧密相连。通常用具体的Java类来实现这个角色。

抽象产品(Abstract Product)角色:工厂方法模式所创建的对象的父类或它们的共同接口,它往往由接口或抽象类来实现。

具体产品(Concrete Product)角色:抽象工厂所创建的任何产品对象都是某一个具体产品的实例。这是客户端最终需要的东西。

 

下面我们就来看看,这几个角色在代码中是怎么展现的。

1、创建抽象产品,这里我们创建两个抽象产品。两个动物类别(哺乳动物和鸟类动物)。

package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 哺乳动物接口
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 9, 2008
 * Copyright: Copyright (c) 2008
 */
public interface ILactationAnimal {
 
	/**
	 * 哺乳
	 */
	public void suckle();
 
	/**
	 * 胎生
	 */
	public void viviparity();
 
}
? Download IBirdAnimal.java
package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 鸟类动物接口
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 9, 2008
 * Copyright: Copyright (c) 2008
 */
public interface IBirdAnimal {
 
	/**
	 * 飞行
	 */
	public void fly();
 
}

2、创建具体产品都是实现抽象产品的接口来的。

? Download dog.java
package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 狗类实现哺乳动物接口
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 9, 2008
 * Copyright: Copyright (c) 2008
 */
public class Dog implements ILactationAnimal {
 
	/**
	 * 哺乳
	 */
	public void suckle() {
		print("狗狗正在哺乳");
	}
 
	/**
	 * 胎生
	 */
	public void viviparity() {
		print("狗妈妈要生小狗狗了");
	}
 
	/**
	 * 打印输出的辅助方法
	 * @param message 打印内容
	 */
	public static void print(String message) {
		System.out.println(message);
	}
 
}
? Download Magpie.java
package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 喜鹊实现鸟类接口
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 9, 2008
 * Copyright: Copyright (c) 2008
 */
public class Magpie implements IBirdAnimal {
 
	/**
	 * 飞行
	 */
	public void fly() {
		print("喜鹊在空中飞");
	}
 
	/**
	 * 打印输出的辅助方法
	 * @param message 打印内容
	 */
	public static void print(String message){
		System.out.println(message);
	}
 
}

3、这下我们的代码就有层次结构关系了。哺乳类(狗),鸟类(喜鹊)。那下面我们就来创建抽象工厂吧。

package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 抽象工厂角色,工厂的核心类
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 9, 2008
 * Copyright: Copyright (c) 2008
 */
public interface IAnimalFactory {
 
	/**
	 * 工厂方法
	 * @return 鸟类接口
	 */
	public IBirdAnimal birdFactory();
 
	/**
	 * 工厂方法
	 * @return 哺乳类接口
	 */
	public ILactationAnimal lactationFactory();
 
}

4、创建具体工厂类,必须实现抽象工厂这个接口或者抽象类。

? Download AnimalFactory.java
package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 具体工厂,动物工厂
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 9, 2008
 * Copyright: Copyright (c) 2008
 */
public class AnimalFactory implements IAnimalFactory {
 
	/**
	 * 实现工厂方法
	 */
	public IBirdAnimal birdFactory() {
		return new Magpie();
	}
 
	/**
	 * 实现工厂方法
	 */
	public ILactationAnimal lactationFactory() {
		return new Dog();
	}
 
}

5、测试一下我们所做的结果,和前面的两个工厂有什么不同吧。

? Download test.java
package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 测试类
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 10, 2008
 * Copyright: Copyright (c) 2008
 */
public class Test {
 
   /**
    * AnimalFactory这个具体工厂在客户端的调用下创建产品的实例。
   */
    public static void main(String[] args) {
        IBirdAnimal magpie = new AnimalFactory().birdFactory();
        magpie.fly();
 
        ILactationAnimal dog = new AnimalFactory().lactationFactory();
        dog.suckle();
        dog.viviparity();
 
    }
 
}

6、客户端所要的结果是出来了,那到底抽象工厂模式的好处在哪?现在和大家讲讲它所支持的“开-闭”原则(理论在“JAVA设计模式之简单工厂(Simple Factory)模式”中提到过,有兴趣的可以看看,在这不再啰嗦)。

现在我们要做的就是不修改原来代码的基础上,加上一个新功能。比方说,我们加个猪类(哺乳动物)和布谷鸟(鸟类)。

6.1、创建具体产品吧。

? Download pig.java
package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 猪类实现哺乳动物接口
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 9, 2008
 * Copyright: Copyright (c) 2008
 */
public class Pig implements ILactationAnimal {
 
	/**
	 * 哺乳
	 */
	public void suckle() {
		print("猪猪正在哺乳");
	}
 
	/**
	 * 胎生
	 */
	public void viviparity() {
		print("猪妈妈要生小猪猪了");
	}
 
	/**
	 * 打印输出的辅助方法
	 * @param message 打印内容
	 */
	public static void print(String message) {
		System.out.println(message);
	}
 
}
? Download Cuckoo.java
package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 布谷鸟类
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 9, 2008
 * Copyright: Copyright (c) 2008
 */
public class Cuckoo implements IBirdAnimal {
 
	/**
	 * 飞行
	 */
	public void fly() {
		print("布谷鸟在田里飞");
	}
 
	/**
	 * 打印输出的辅助方法
	 * @param message 打印内容
	 */
	public static void print(String message){
		System.out.println(message);
	}
 
}

6.1.2、我们可以在不用修改原代码的基础上,再创建一个新的具体工厂。

package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 新加的具体工厂
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 10, 2008
 * Copyright: Copyright (c) 2008
 */
public class NewAnimalFactory implements IAnimalFactory {
 
	public IBirdAnimal birdFactory() {
		return new Cuckoo();
	}
 
	public ILactationAnimal lactationFactory() {
		return new Pig();
	}
 
}

6.1.3、测试下,看是不是一切OK了,要加什么产品完全不用去修改原代码,想要什么就加什么。

? Download test.java
package org.dbablog.abstractfactory;
 
/**
 * Title: DesignPattern
 * Description: 测试类
 * Work: Programmer
 * @author 蛋蛋
 * @version 1.0
 * @Date Sep 10, 2008
 * Copyright: Copyright (c) 2008
 */
public class Test {
 
   /**
    * AnimalFactory这个具体工厂在客户端的调用下创建产品的实例。
   */
    public static void main(String[] args) {
        IBirdAnimal magpie = new AnimalFactory().birdFactory();
        magpie.fly();
 
        ILactationAnimal dog = new AnimalFactory().lactationFactory();
        dog.suckle();
        dog.viviparity();
 
        IBirdAnimal cuckoo = new NewAnimalFactory().birdFactory();
        cuckoo.fly();
 
        ILactationAnimal pig = new NewAnimalFactory().lactationFactory();
        pig.suckle();
        pig.viviparity();
    }
 
}

总结:

在什么情况下使用抽象工厂模式?

  • 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节。这对于所有的工厂模式都是重要的。
  • 这个系统的产品有多余一个产品族,而系统只消费某一族的产品。
  • 同属于一个产品族中的产品是在一起使用的,这一约束必须在系统的设计中体现出来的。
  • 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值