查看: 1527|回复: 0

[PHP实例] Java设计模式----------抽象工厂模式

发表于 2018-3-13 08:00:11
1、介绍

意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

主要解决:主要解决接口选择的问题。

何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。

如何解决:在一个产品族里面,定义多个产品。每个具体的工厂负责一个产品族。抽象工厂的返回值为最高级抽象产品。

关键代码:在一个工厂里聚合多个同类产品(在同一个产品族中)。

应用实例:举一个衣服与衣柜的例子。家里边,有男装(产品族,其中包含休闲男装和商务男装)、女装(产品族,其中包含休闲女装和商务女装)。商务女装、商务男装、时尚女装、时尚男装,这些都是具体产品。男装专门放在男衣柜(具体工厂)中,女装专门放在女衣柜(具体工厂)中。当我们需要拿衣服时候,从衣柜(抽象工厂)中获取。

所以抽象工厂,非常适合解决两个维度的组合产品的构造问题,取其中一个维度作为产品族,另外一个维度作为产品族中具体的多个产品。

优点:能够从多个产品族的多个产品中,简洁的获取想要的具体产品。解决了工厂模式中的不符合开闭原则的问题(增加新的产品时候,不修改工厂,而是增加工厂)。

缺点:产品族扩展比较困难,要增加一个系列的某一产品,要增加具体的产品类,还要增加对应的工厂类(或者修改对应产品族的工厂类)。

使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。

注意事项:产品族难扩展,产品等级易扩展。

2、案例 2.1、背景

还是举买车的例子。

某客户想要购买一辆车,他要联系4S店,首先得有4S店(抽象工厂)的电话。

客户上网查询(建造工厂),发现了宝马4S店(具体工厂)的电话和奔驰4S店(具体工厂)的电话。

客户拨通了宝马4S店的电话(获取具体工厂),发现目前店里可以提供(生产)多款车型(具体产品)供客户选择(BMW 320、BMW 530,BMW 740)。

客户拨通了奔驰4S店的电话(获取具体工厂),发现目前店里可以提供(生产)多款车型(具体产品)供客户选择(BenzC200、BenzE300)。

2.2、实现 汽车类
  1. /**
  2. * 最高级抽象产品,用于抽象工厂的建造方法的返回值
  3. */
  4. public abstract class Car
  5. {
  6. abstract void drive();
  7. }
复制代码
宝马产品类
  1. /**
  2. * 抽象产品
  3. */
  4. public abstract class BMWCar extends Car
  5. {
  6. }
复制代码
  1. /**
  2. * 具体产品BMW320
  3. */
  4. public class BMW320 extends BMWCar
  5. {
  6. public void drive()
  7. {
  8. System.out.println("BMW320,运动酷炫。");
  9. }
  10. }
复制代码
  1. /**
  2. * 具体产品BMW530
  3. */
  4. public class BMW530 extends BMWCar
  5. {
  6. public void drive()
  7. {
  8. System.out.println("BMW530,时不我待。");
  9. }
  10. }
复制代码
  1. /**
  2. * 具体产品BMW740
  3. */
  4. public class BMW740 extends BMWCar
  5. {
  6. public void drive()
  7. {
  8. System.out.println("BMW740,高端商务。");
  9. }
  10. }
复制代码
奔驰产品类
  1. /**
  2. * 抽象产品
  3. */
  4. public abstract class BenzCar extends Car
  5. {
  6. }
复制代码
  1. /**
  2. * 具体产品C200
  3. */
  4. public class BenzC200 extends BenzCar
  5. {
  6. public void drive()
  7. {
  8. System.out.println("BenzC200,实惠有面");
  9. }
  10. }
复制代码
  1. /**
  2. * 具体产品E300
  3. */
  4. public class BenzE300 extends BenzCar
  5. {
  6. public void drive()
  7. {
  8. System.out.println("BenzE300,商务气派");
  9. }
  10. }
复制代码
工厂类
  1. /**
  2. * 奔驰工厂,覆盖所有奔驰车型的构造方法
  3. */
  4. public class BenzFactory extends AbstractFactory
  5. {
  6. public Car getCar(String type) throws ClassNotFoundException,
  7. IllegalAccessException, InstantiationException
  8. {
  9. Class cl = Class.forName(type);
  10. return (BenzCar)cl.newInstance();
  11. }
  12. }
复制代码
  1. /**
  2. * 宝马工厂,覆盖所有宝马车型的构造方法
  3. */
  4. public class BMWFactory extends AbstractFactory
  5. {
  6. public Car getCar(String type) throws ClassNotFoundException,
  7. IllegalAccessException, InstantiationException
  8. {
  9. Class cl = Class.forName(type);
  10. return (BMWCar)cl.newInstance();
  11. }
  12. }
复制代码
抽象工厂类
  1. public abstract class AbstractFactory
  2. {
  3. public abstract Car getCar(String type) throws ClassNotFoundException,
  4. IllegalAccessException, InstantiationException;
  5. }
复制代码
超级工厂类
  1. /**
  2. * 超级工厂类,建造工厂的工厂
  3. */
  4. public class FactoryProducer
  5. {
  6. public static AbstractFactory getFactory(String type)
  7. throws IllegalAccessException, InstantiationException, ClassNotFoundException
  8. {
  9. Class cl = Class.forName(type);
  10. System.out.println("创建工厂"+type);
  11. return (AbstractFactory)cl.newInstance();
  12. }
  13. }
复制代码
验证
  1. /**
  2. * 验证
  3. */
  4. public class Demo
  5. {
  6. public static void main(String[] args) throws IllegalAccessException,
  7. InstantiationException, ClassNotFoundException
  8. {
  9. AbstractFactory abstractFactory = FactoryProducer.getFactory("BMWFactory");
  10. Car bmwCar = abstractFactory.getCar("BMW320");
  11. bmwCar.drive();
  12. Car bmwCar1 = abstractFactory.getCar("BMW530");
  13. bmwCar1.drive();
  14. Car bmwCar2 = abstractFactory.getCar("BMW740");
  15. bmwCar2.drive();
  16. AbstractFactory abstractFactory1 = FactoryProducer.getFactory("BenzFactory");
  17. Car benzCar = abstractFactory1.getCar("BenzC200");
  18. benzCar.drive();
  19. Car benzCar1 = abstractFactory1.getCar("BenzE300");
  20. benzCar1.drive();
  21. }
  22. }
复制代码

运行结果如下如所示:
图片描述

3、总结

抽象工厂模式非常针对2个维度描述的产品的构造问题。取其中一个维度作为产品族(也就是对应一个具体工厂),另外一个维度作为产品族下的具体产品。从这个角度说,抽象工厂模式是在工厂模式基础上,做了一个维度的升级。

举例,比如商务男装,商务女装,时尚男装,时尚女装的选择问题。取男装为一个产品族,对应一个工厂;取女装作为一个产品族,对应一个工厂。每个工厂中会生产多种类型(商务或者时尚)的衣服。



回复

使用道具 举报