博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
模式11. 抽象工厂模式-Java
阅读量:4034 次
发布时间:2019-05-24

本文共 11908 字,大约阅读时间需要 39 分钟。

1.定义

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

2.借助(数据库访问)场景理解

2.1单类的时候,只需工厂方法模式

对象:用户

数据库:数据库:两种方式 SQLserver以及 Access

用工厂方法模式的数据库访问程序

在这里插入图片描述

(1)Iuser接口

package com.factory;//IUSer接口,用于客户端访问,解除与具体数据库访问的耦合public interface Iuser {
void Insert(User user); User GetUser(int id);}

(2)

package com.factory;//用于访问Sql Server的Userpublic class SqlserverUser implements  Iuser{
@Override public void Insert(User user) {
System.out.println("在Sql Server中给User表增加一条记录"); } @Override public User GetUser(int id) {
System.out.println("在Sql Server中给根据ID得到User表的一条记录"); return null; }}

(3)

package com.factory;//用于访问Access的Userpublic class AccessUser implements Iuser{
@Override public void Insert(User user) {
System.out.println("在Access中给User表增加一条记录"); } @Override public User GetUser(int id) {
System.out.println("在Access中给根据ID得到User表的一条记录"); return null; }}

(4)

package com.factory;//定义一个创建访问User表对象的抽象的工厂接口public interface IFactory {
Iuser CreateUser();}

(5)

package com.factory;//实例化SqlserverUserpublic class SqlServerFactory implements IFactory {
@Override public Iuser CreateUser() {
return new SqlserverUser(); }}

(6)

package com.factory;public class AccessFactory implements IFactory{
@Override public Iuser CreateUser() {
return new AccessUser(); }}

(7)客户端代码

package com.factory;public class AccessFactory implements IFactory{
@Override public Iuser CreateUser() {
return new AccessUser(); }}

(8)测试结果

在Sql Server中给User表增加一条记录在Sql Server中给根据ID得到User表的一条记录

2.2多类的时候,体现抽象工厂模式

对象: 用户,以及部门

数据库:两种方式 SQLserver以及 Access

在这里插入图片描述

和2.1相比,增加如下代码

(1) 部门类

package com.abstractfactory;public class Department {
private int id; private String name; public int getId() {
return id; } public void setId(int id) {
this.id = id; } public String getName() {
return name; } public void setName(String name) {
this.name = name; }}

(2)Idepartment接口, 用于客户端访问,解除与具体数据库

package com.abstractfactory;public interface Idepartment {
void Insert(Department department); Department GetUser(int id);}

(3)SqlServerDepartment类,用于Sqlserver操作department表

package com.abstractfactory;public class SqlserverDepartment implements  Idepartment{
@Override public void Insert(Department department) {
System.out.println("在SqlServer中向department表插一条记录"); } @Override public Department GetUser(int id) {
System.out.println("在Sqlserver中给根据ID得到department表的一条记录"); return null; }}

(4)同理Accessdepartment

package com.abstractfactory;public class AccessDepartment implements Idepartment{
@Override public void Insert(Department department) {
System.out.println("在ACcess中向department表插一条记录"); } @Override public Department GetUser(int id) {
System.out.println("在Access中给根据ID得到department表的一条记录"); return null; }}

(5)修改Ifactory

package com.abstractfactory;//定义一个创建访问User表对象的抽象的工厂接口public interface IFactory {
Iuser CreateUser(); Idepartment CreateDepartment();}

(6)修改SqlserverFactory

package com.abstractfactory;//实例化SqlserverUserpublic class SqlServerFactory implements IFactory {
@Override public Iuser CreateUser() {
return new SqlserverUser(); } @Override public Idepartment CreateDepartment() {
return new SqlserverDepartment(); }}

(7)修改AccessFactory

package com.abstractfactory;public class AccessFactory implements IFactory {
@Override public Iuser CreateUser() {
return new AccessUser(); } @Override public Idepartment CreateDepartment() {
return new AccessDepartment(); }}

(8)客户端

package com.abstractfactory;public class Client {
public static void main(String[] args) {
User user =new User(); Department department=new Department(); IFactory factory=new AccessFactory();//若要改变为Access数据库,只需将本句改为 // IFactory factory=new SqlServerFactory(); Iuser iuser=factory.CreateUser(); //与具体数据库访问解除了依赖 Idepartment idepartment=factory.CreateDepartment(); iuser.Insert(user); iuser.GetUser(1); idepartment.Insert(department); idepartment.GetUser(1); }}

(9)测试结果

在Access中给User表增加一条记录在Access中给根据ID得到User表的一条记录在ACcess中向department表插一条记录在Access中给根据ID得到department表的一条记录

3.抽象工厂模式优缺点

在这里插入图片描述

  • Ifactory中包含所有产品创建的抽象方法。

  • 为创建不同的产品对象,客户端使用不同的具体工厂。

    优点

    • 便于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,使得改变一个应用的具体工厂变得非常容易,只需要改变具体工厂即可使用不同的产品配置
    • 让具体的创建实例过程与客户端分离。客户端时通过他们的抽象接口比如Iuser操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中

    缺点

    增加实体类的时候要改动很多地方,比如增加company表,就需要增加ICompany接口,SqlserverFactory,AccessFactory,还需要改动Ifactory, SqlserverCompany以及AccessFactory

4.用简单工厂一定程度优化抽象工厂

在这里插入图片描述

设计Dataaccess类,

package com.simpleFactory;public class DataAccess {
private static String db="SqlServer"; //在这里该数据库类型 //private static String db="Access"; public static Iuser CreateUser(){
Iuser result=null; switch (db){
//前边已经选好了数据库 case "Sqlserver": result=new SqlserverUser(); break; case "Access": result=new AccessUser(); break; } return result; } public static Idepartment CreateIdepartement(){
Idepartment result=null; switch (db){
case "Sqlserver": result=new SqlserverDepartment(); break; case "Access": result=new AccessDepartment(); break; } return result; }}

更改客户端

package com.simpleFactory;public class Client {
public static void main(String[] args) {
User user =new User(); Department department=new Department(); //因为事先选好了用的数据库,所以可以直接得到数据库访问实例,客户不需要了解是用的什么数据库 Iuser iuser=DataAccess.CreateUser(); //因为设置的都是静态函数,直接用 Idepartment idepartment= (Idepartment) DataAccess.CreateIdepartement(); iuser.Insert(user); iuser.GetUser(1); idepartment.Insert(department); idepartment.GetUser(1); }}

简单工厂方法的确实现了客户端不需要知道Sqlser和ACcess数据库, 但是如果再加一个数据库比如oracle,就不是抽象工厂方法中增加oracleFactory那么简单了,需要再DataAccess的每个函数中的switch中加Case

5.反射+抽象工厂模式

  • 利用反射,使用字符串来实例化对象。而不再是写死再程序中

在这里插入图片描述

JAVA反射机制是就是运行的状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。通过反射机制可以动态的访问类的属性和方法以及字段。

最常用的反射机制就是:

(类)Class.forName("obj name").newInstance();
package com.reflection;public class DataAccess {
private static String AssemblyName="com.reflection"; //根目录Src下的路径 private static String db="Sqlserver"; //可以替换成任意类型的数据库,比如access public static Iuser CreateUser() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String classname=AssemblyName+"."+db+"User"; return (Iuser)Class.forName(classname).newInstance(); //根据字符串 "com.reflection.SqlserverUser"匹配com.reflection.SqlserverUser类 } public static Idepartment CreateIdepartment() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String classname=AssemblyName+"."+db+"Department"; return (Idepartment) Class.forName(classname).newInstance(); }}

成功的前提是com.reflection.SqlserverUser,SqlserverDepartment这些类存在

客户端没有变化

package com.reflection;public class Client {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
User user =new User(); Department department=new Department(); Iuser iuser= DataAccess.CreateUser(); Idepartment idepartment= DataAccess.CreateIdepartment(); iuser.Insert(user); iuser.GetUser(1); idepartment.Insert(department); idepartment.GetUser(1); }}

执行结果

在Sql Server中给User表增加一条记录在Sql Server中给根据ID得到User表的一条记录在SqlServer中向department表插一条记录在Sqlserver中给根据ID得到department表的一条记录

6.用反射+配置文件+抽象工厂模式(end,最理想)

完整代码:

(1)实体类

package com.reflection;public class User {
private int _id; private String _name; public int get_id() {
return _id; } public void set_id(int _id) {
this._id = _id; } public String get_name() {
return _name; } public void set_name(String _name) {
this._name = _name; }}
package com.reflection;public class Department {
private int id; private String name; public int getId() {
return id; } public void setId(int id) {
this.id = id; } public String getName() {
return name; } public void setName(String name) {
this.name = name; }}

(2) 实体表接口,事先客户端与实体表的解耦

package com.reflection;//IUSer接口,用于客户端访问,解除与具体数据库访问的耦合public interface Iuser {
void Insert(User user); User GetUser(int id);}
package com.reflection;public interface Idepartment {
void Insert(Department department); Department GetUser(int id);}

(3) 具体数据库操作每个实体

Access数据库

package com.reflection;//用于访问Access的Userpublic class AccessUser implements Iuser {
@Override public void Insert(User user) {
System.out.println("在Access中给User表增加一条记录"); } @Override public User GetUser(int id) {
System.out.println("在Access中给根据ID得到User表的一条记录"); return null; }}
package com.reflection;public class AccessDepartment implements Idepartment {
@Override public void Insert(Department department) {
System.out.println("在ACcess中向department表插一条记录"); } @Override public Department GetUser(int id) {
System.out.println("在Access中给根据ID得到department表的一条记录"); return null; }}

Sql server数据库

package com.reflection;//用于访问Sql Server的Userpublic class SqlserverUser implements Iuser {
@Override public void Insert(User user) {
System.out.println("在Sql Server中给User表增加一条记录"); } @Override public User GetUser(int id) {
System.out.println("在Sql Server中给根据ID得到User表的一条记录"); return null; }}
package com.reflection;public class SqlserverDepartment implements Idepartment {
@Override public void Insert(Department department) {
System.out.println("在SqlServer中向department表插一条记录"); } @Override public Department GetUser(int id) {
System.out.println("在Sqlserver中给根据ID得到department表的一条记录"); return null; }}

(4) 数据库抽象工厂, 利用配置文件+反射

使用反射替代了简单工厂的switch

用户改数据库类型,只需在配置文件中改!

db=Access
package com.reflection;import java.util.ResourceBundle;public class DataAccess {
private static String AssemblyName="com.reflection"; //读取配置文件中的db类型 ResourceBundle resource1=ResourceBundle.getBundle("com/reflection/App"); //通过用户输入的来取指定类 private String db=resource1.getString("db"); //可以替换成任意类型的数据库,比如access public Iuser CreateUser() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String classname=AssemblyName+"."+db+"User"; return (Iuser)Class.forName(classname).newInstance(); } public Idepartment CreateIdepartment() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String classname=AssemblyName+"."+db+"Department"; return (Idepartment) Class.forName(classname).newInstance(); }}

(5)客户端

package com.reflection;public class Client {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
User user =new User(); Department department=new Department(); DataAccess dataAccess=new DataAccess(); Iuser iuser= dataAccess.CreateUser(); Idepartment idepartment= dataAccess.CreateIdepartment(); iuser.Insert(user); iuser.GetUser(1); idepartment.Insert(department); idepartment.GetUser(1); }}

运行结果

在Access中给User表增加一条记录在Access中给根据ID得到User表的一条记录在ACcess中向department表插一条记录在Access中给根据ID得到department表的一条记录

转载地址:http://dvfdi.baihongyu.com/

你可能感兴趣的文章
Android/Linux 内存监视
查看>>
Linux系统信息查看
查看>>
用find命令查找最近修改过的文件
查看>>
Android2.1消息应用(Messaging)源码学习笔记
查看>>
Phone双模修改涉及文件列表
查看>>
android UI小知识点
查看>>
Android之TelephonyManager类的方法详解
查看>>
android raw读取超过1M文件的方法
查看>>
ubuntu下SVN服务器安装配置
查看>>
MPMoviePlayerViewController和MPMoviePlayerController的使用
查看>>
CocoaPods实践之制作篇
查看>>
[Mac]Mac 操作系统 常见技巧
查看>>
苹果Swift编程语言入门教程【中文版】
查看>>
捕鱼忍者(ninja fishing)之游戏指南+游戏攻略+游戏体验
查看>>
iphone开发基础之objective-c学习
查看>>
iphone开发之SDK研究(待续)
查看>>
计算机网络复习要点
查看>>
Variable property attributes or Modifiers in iOS
查看>>
NSNotificationCenter 用法总结
查看>>
C primer plus 基础总结(一)
查看>>