模式导读:
所谓抽象工厂模式就是它提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确指定具体类,允许客户端使用抽象的接口来创建一组相关的产品,而不需要关系实际产出的具体产品是什么。这样一来,客户就可以从具体的产品中被解耦。它的优点是隔离了具体类的生成,使得客户端不需要知道什么被创建了,而缺点就在于新增新的行为会比较麻烦,因为当添加一个新的产品对象时,需要更改接口及其下所有子类。
参考类图
代码实现
1.定义一个接口用于实现获取工厂内产品的方法
1 package com.etc; 2 3 // 定义一个接口用于实现获取工厂内产品的方法 4 public interface AbstractComputerFactory { 5 6 Computer getComputer(String msg); 7 8 }
1 package com.etc; 2 3 // 定义一个接口用于实现获取工厂内产品的方法 4 public interface AbstractPhoneFactory{ 5 6 Phone getPhone(String msg); 7 8 }
2.定义具体的工厂类实现抽象工厂内获取具体产品的方法
(1)ComputerFactory.java
1 package com.etc; 2 3 //定义具体的工厂类实现抽象工厂内获取具体产品的方法 4 public class ComputerFactory implements AbstractComputerFactory { 5 // 根据用户需求给定产品 6 public Computer getComputer(String msg) { 7 if ("联想".equals(msg)) { 8 return new LenovoComputer(); 9 } else if ("苹果".equals(msg)) { 10 return new AppleComputer(); 11 } 12 return null; 13 } 14 15 }
(2)PhoneFactory.java
1 package com.etc; 2 3 //定义具体的工厂类实现抽象工厂内获取具体产品的方法 4 public class PhoneFactory implements AbstractPhoneFactory { 5 6 public Phone getPhone(String msg) { 7 if ("联想".equals(msg)) { 8 return new LenovoPhone(); 9 } else if ("苹果".equals(msg)) { 10 return new ApplePhone(); 11 } 12 return null; 13 } 14 15 }
3.定义抽象产品类,里面定义获取具体产品信息的方法
(1)Computer.java
1 package com.etc; 2 3 public interface Computer { 4 //定义一个接口实现产品电脑信息的打印 5 public void print(); 6 7 }
(2)Phone.java
1 package com.etc; 2 3 public interface Phone { 4 //定义一个接口实现产品手机信息的打印 5 public void fill(); 6 }
4.定义具体的产品实现类,里面实现打印出产品的信息的方法
(1)LenovoComputer.java
1 package com.etc; 2 3 public class LenovoComputer implements Computer { 4 5 @Override 6 public void print() { 7 System.out.println("这是一台联想电脑!"); 8 } 9 10 }
(2)LenovoPhone.java
1 package com.etc; 2 3 public class LenovoPhone implements Phone { 4 5 @Override 6 public void fill() { 7 System.out.println("这是一部联想手机!"); 8 } 9 10 }
(3)ApplePhone.java
1 package com.etc; 2 3 public class ApplePhone implements Phone { 4 //工厂内具体产品苹果手机打印 5 @Override 6 public void fill() { 7 System.out.println("这是一部苹果手机!"); 8 } 9 10 }
(4)AppleComputer.java
1 package com.etc; 2 3 public class AppleComputer implements Computer{ 4 5 @Override 6 public void print() { 7 System.out.println("这是一台苹果电脑!"); 8 } 9 10 }
5.定义一个类用于实现根据用户具体需求获取哪一个工厂
1 package com.etc; 2 3 //获得指定工厂 4 public class Producer { 5 6 private static AbstractPhoneFactory phoneFactory = null; 7 private static AbstractComputerFactory computerFactory = null; 8 9 private Producer() { 10 11 } 12 13 // 获得手机工厂 14 public static AbstractPhoneFactory getPhoneFactory() { 15 phoneFactory = new PhoneFactory(); 16 return phoneFactory; 17 } 18 19 // 获得电脑工厂 20 public static AbstractComputerFactory getComputerFactory() { 21 computerFactory = new ComputerFactory(); 22 return computerFactory; 23 } 24 }
6.定义一个测试类
1 package com.etc; 2 3 public class Test { 4 5 public static void main(String[] args) { 6 // 用户需要电脑,且具体产品为苹果电脑 7 Producer.getComputerFactory().getComputer("苹果").print(); 8 // 用户需要手机,且具体产品为联想手机 9 Producer.getPhoneFactory().getPhone("联想").fill(); 10 11 } 12 13 }
效果截图
抽象工厂模式优缺点:
优点:
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:
产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
适用场景:
1.系统不依赖于产品类实例如何被创建,组合和表达的细节。
2.系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
3.同属于同一个产品族是在一起使用的。这一约束必须在系统的设计中体现出来。
4.系统提供一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖于实现。