首页 > 其他 > 详细

设计模式(二)工厂模式:3-抽象工厂模式

时间:2017-09-18 17:58:27      阅读:353      评论:0      收藏:0      [点我收藏+]

 

 

  抽象工厂模式,相对于前2种工厂模式,引入了“产品族”的概念。

  何为产品族?以之前的运算器为例,之前讨论的都是局限于“运算器”这个产品,而现在,我要为其加上前缀:“工厂1生产的运算器”,“工厂2生产的运算器”。

  这就是产品族,对象拥有相同的行为,但却是有不同的实现。

  那么现在来看,运算器这个例子,可能已经不能特别直观地,将抽象工厂模式展示出来,我们换一个场景。

 

 

模拟场景:

 

  我需要去创建用户(User)和部门(Department)两个对象,但是底层需要用的数据库(DB2 和 MySQL),可能产生变化,所以需要两套解决方案。

 

 

思想:

 

  首先,针对需要创建的对象,需要一个抽象工厂(AbsFactory),负责创建抽象用户(AbsUser)和抽象部门(AbsDepartment)。

  根据底层的数据库,抽象工厂拥有两个实现,DB2 工厂(FactoryDB2)和 MySQL 工厂(FactoryMySQL)。

  每个工厂各司其职,创建对应的继承抽象类的对象。

 

 

UML:

 

技术分享

 

分析:

 

  以上是一个针对给出情景的完整 UML 类图。

  为用户(User)定义了两种行为,而部门(Department)没有定义方法。

  在用户的 joinDepartment() 方法中,缺少一条依赖(Dependency)的虚线。由于多态的性质对于入参无能为力,所以类似的情形,需要在方法内部进行向下转型。

  可以看出,抽象方法模式(Abstract Factory),其实就是将多个工厂方法模式(Factory Method)组装在一起。

 

 

代码:

 

技术分享
1 public abstract class AbsFactory {
2 
3     protected abstract AbsUser createUser();
4 
5     protected abstract AbsDepartment createDepartment();
6 
7 }
AbsFactory
技术分享
 1 public abstract class AbsUser {
 2 
 3     protected void joinDepartment(AbsDepartment department) {
 4         System.out.println(this.toString() + "不能加入任何部门");
 5     }
 6 
 7     protected abstract void personalMethod();
 8 
 9     @Override
10     public String toString() {
11         return this.getClass().getSimpleName().substring(4) + "用户";
12     }
13 
14 }
AbsUser
技术分享
1 public abstract class AbsDepartment {
2 
3     @Override
4     public String toString() {
5         return this.getClass().getSimpleName().substring(10) + "部门";
6     }
7 
8 }
AbsDepartment

 

技术分享
 1 public final class FactoryDB2 extends AbsFactory {
 2 
 3     @Override
 4     public UserDB2 createUser() {
 5         return new UserDB2();
 6     }
 7 
 8     @Override
 9     public DepartmentDB2 createDepartment() {
10         return new DepartmentDB2();
11     }
12 
13 }
FactoryDB2
技术分享
 1 public final class FactoryMySQL extends AbsFactory {
 2 
 3     @Override
 4     public UserMySQL createUser() {
 5         return new UserMySQL();
 6     }
 7 
 8     @Override
 9     public DepartmentMySQL createDepartment() {
10         return new DepartmentMySQL();
11     }
12 
13 }
FactoryMySQL

 

技术分享
1 public final class UserDB2 extends AbsUser {
2 
3     @Override
4     public void personalMethod() {
5         System.out.println("DB2用户的个人行为");
6     }
7 
8 }
UserDB2
技术分享
 1 public final class UserMySQL extends AbsUser {
 2 
 3     @Override
 4     public void personalMethod() {
 5         System.out.println("MySQL用户的个人行为");
 6     }
 7 
 8     @Override
 9     public void joinDepartment(AbsDepartment department) {
10         if (department instanceof DepartmentMySQL) {
11             department = (DepartmentMySQL) department;
12         } else {
13             throw new RuntimeException("只接受 MySQL数据库创建的部门");
14         }
15         System.out.println(this.toString() + "加入部门:" + department.toString());
16     }
17 
18 }
UserMySQL

 

技术分享
1 public final class DepartmentDB2 extends AbsDepartment {
2 
3 }
DepartmentDB2
技术分享
1 public final class DepartmentMySQL extends AbsDepartment {
2 
3 }
DepartmentMySQL

 

 

Junit 即测试客户端调用:

 

技术分享
 1 public final class AbsFactoryTest {
 2 
 3     @Test
 4     public void test1() {
 5         AbsUser user = new UserDB2();
 6         AbsDepartment department = new DepartmentDB2();
 7         user.joinDepartment(department);
 8         user.personalMethod();
 9     }
10 
11     @Test
12     public void test2() {
13         AbsUser user = new UserMySQL();
14         AbsDepartment department = new DepartmentMySQL();
15         user.joinDepartment(department);
16         user.personalMethod();
17     }
18 
19 }
JUnit

 

JUnit 控制台输出:

 

技术分享

 

 

总结:

 

  从客户端的调用情况,可以发现,只要修改顶层工厂(每个产品的抽象父类,对应在工厂方法模式中,就是一个工厂)的方式,就可以改变创建的具体对象,体现了良好的封装性。

  产品具体的约束,由产品内部实现,客户端无需关心。

  使用抽象工厂模式,在设计之初,必须考虑到 AbsFactory 中生产的所有对象。如果后期需要在工厂中多生产一个角色(Role),不但修改困难,而且从顶层开始就破坏了封装性,违反了开闭原则。

  如果需要增加一种对象实现的方式,比如 Oracle 实现,虽然要增加的对象同样很多,但是既不会打破代码的封装性,也不会与现有的代码产生耦合,是可以接受的情况。

  抽象工厂模式,去除那些业务场景之外,在数据库连接(ORM 框架)和操作系统相关(Java 的平台无关性),有着很好的实践。

 

设计模式(二)工厂模式:3-抽象工厂模式

原文:http://www.cnblogs.com/jing-an-feng-shao/p/7544309.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!