No deseño de patróns, o **patrón DAO (*Data Access Object*)** dispón dunha interface para os mecanismos de persistencia dos datos aínda que comunmente se emprega para o uso das bases de datos.
Aínda que este patrón de deseño e aplicable na maioría dos linguaxes de programación, asociase tradicionalmente con aplicacións *Java EE* e as bases de datos relacionais accedese a través da *API JDBC*, debido a súa orixe en *Sun Microsystems* para esta plataforma.

Contexto
--------

Dentro da maioría das aplicacións necesitase gardar os datos de maneira persistente para que o saír da aplicación os datos poidan estar almacenados dalgunha forma e nalgún lugar (xa sexa unha base de datos obxectual, unha base de datos relacional, arquivos XML...) para que o volver a usar a aplicación esta poida cargalos e continuar traballando con eles. Para cada mecanismo de almacenamento existen múltiples formas de acceder aos datos e isto e algo que a lóxica de negocio non lle debería de afectar e por iso necesitase abstraer todo ese coñecemento e "envolvelo" nunha capa.

O patrón DAO (Obxecto de Acceso a Datos) mostra unha maneira de encapsular ese coñecemento e así evita que a lóxica de negocio coñeza esa tarefa, de tal maneira que se nalgún intre requirise cambiar a maneira de acceder aos datos non afecte a lóxica de negocio. A información que se obtén das fontes de datos é convertida (ou encapsulada) nun obxecto de tipo *TransferObject* (ou unha colección deles), que, simplificando non son máis que "caixas de información".

Manexando múltiples fontes de datos: Patrón *Factory*
-----------------------------------------------------

En ocasión pode ocorrer que unha aplicación necesite facer uso de varias fontes de datos, o que se traduce en ter varios mecanismos para ter a información. Supoñamos que necesitamos acceder aos datos de tres formas distintas: unha mediante arquivos TXT, outra mediante ficheiros XLS e a última de todas cunha base de datos relacional, as cales gardan información sobre usuarios. O patrón *Factory* soluciónanos o problema de procurar que a capa de negocio non coñeza a maneira en que se obtén os datos.

Agora mostrase un pouco de código en *Java* para poder ter unha idea de como é a implementación:

**Clase FactoryDao**

```
public abstract class FactoryDao {
 public static final int TXT\_FACTORY = 1;
 public static final int XLS\_FACTORY = 2;
 public static final int ORACLE\_FACTORY = 3;

 public abstract UserDao getUserDao();

 public static FactoryDao getFactory(int key) {
 switch (key) {
 case TXT\_FACTORY:
 return new TxtFactoryDao();
 case XLS\_FACTORY:
 return new XlsFactoryDao();
 case ORACLE\_FACTORY:
 return new OracleFactoryDao();
 default:
 throw new IllegalArgumentException();
 }
}

```

A clase *FactoryDao* é a que realiza a creación dos obxectos *FactoryDaoX* a través do método estático *getFactory(int)* para cada unha das fontes de datos e obriga as subclases que teñan unha implementación do método *getUserDao()*.

**Interface UserDao**

```
public interface UserDao {
 User search(String name);
 void insert(User user);
 void delete(User user);
}

```

**Clase OracleFactoryDao**

```
public class OracleFactoryDao extends FactoryDao {
 @Override
 public UserDao getUserDao() {
 return new OracleUserDao();
 }
}

```

Estende da clase *FactoryDao* e implementa o método *getUsuarioDao()*, xerando un obxecto que emprega a fonte de datos que se necesita (neste caso unha base de datos de *Oracle*).

**Clase XlsFactoryDao**

```
public class XlsFactoryDao extends FactoryDao {
 @Override
 public UserDao getUserDao() {
 return new XlsUserDao();
 }
}

```

Estende da clase *FactoryDao* e implementa o método *getUsuarioDao()*, xerando un obxecto que emprega a fonte de datos que se necesita (neste caso unha folla de cálculo de *Microsoft Excel*).

**Clase TxtFactoryDao**

```
public class TxtFactoryDao extends FactoryDao {
 @Override
 public UserDao getUserDao() {
 return new TxtUserDao();
 }
}

```

Estende da clase *FactoryDao* e implementa o método *getUsuarioDao()*, xerando un obxecto que emprega a fonte de datos que se necesita (neste caso un arquivo de texto plano).

**Clase OracleUserDao**

```
public class OracleUserDao implements UserDao {
 private ConnectionDao cn;

 public OracleUserDao() {
 cn = ConnectionDao.getInstance();
 }

 public User search(String name) {
 throw new UnsupportedOperationException("Not supported yet.");
 }

 public void insert(User user) {
 throw new UnsupportedOperationException("Not supported yet.");
 }

 public void delete(User user) {
 throw new UnsupportedOperationException("Not supported yet.");
 }
}

```

As operacións que realiza esta clase son empregando unha soa fonte de datos (unha base de datos en *Oracle*).

**Clase XlsUserDao**

```
public class XlsUserDao implements UserDao {
 private String path;

 public XlsUserDao(String path) {
 this.path = path;
 }

 public User search(String name) {
 throw new UnsupportedOperationException("Not supported yet.");
 }

 public void insert(User user) {
 throw new UnsupportedOperationException("Not supported yet.");
 }

 public void delete(User user) {
 throw new UnsupportedOperationException("Not supported yet.");
 }
}

```

As operacións que realiza esta clase son empregando unha soa fonte de datos (unha folla de cálculo en *Microsoft Excel*).

**Clase TxtUserDao**

```
public class TxtUserDao implements UserDao {
 private String path;

 public TxtUserDao(String path) {
 this.path = path;
 }

 public User search(String name) {
 throw new UnsupportedOperationException("Not supported yet.");
 }

 public void insert(User user) {
 throw new UnsupportedOperationException("Not supported yet.");
 }

 public void delete(User user) {
 throw new UnsupportedOperationException("Not supported yet.");
 }
}

```

As operacións que realiza esta clase son empregando unha soa fonte de datos (un arquivo en texto plano).

**Clase User**

```
public class User {
 private String name;
 private String lastname;
 private int age;

 //getter's & setter's
}

```

É a clase mediante a que se transforman os datos procedentes das distintas fontes de datos

**Clase Client**

```
public class Client {
 private FactoryDao factory = FactoryDao.getFactory(FactoryDao.TXT\_FACTORY);
 private UserDao userDao = factory.getUserDao();

 public User search(String name) {
 return userDao.search(name);
 }
 
 public void insert(String name, String lastname, int age) {
 User user = new User();
 user.setName(name);
 user.setLastname(lastname);
 user.setAge(age);
 userDao.insert(user);
 }
}

```

Na clase *Client* podemos ver que é a que decide que fonte de datos empregar mediante o método *getFactory(int)* o cal retorna un obxecto que implementa a interface *UserDao*. O resto de operacions sobre *UserDao* son transparentes para a clase *Client* xa que non coñece o proceso que se require para obter e gardar a información.

Para que se emprega o patrón DAO?
---------------------------------

* Para abstraer e encapsular os accesos os datos.
* Para xestionar as conexións as fontes de datos.
* Para poder ter os datos almacenados.

Patróns comunmente relacionados có patrón DAO
---------------------------------------------

* *Transfer Object*: a información que se envía/recibe do DAO "empaquetase" nestes obxectos.
* *Factory*: co obxecto de conseguir a independencia no almacén dos datos, comunmente emprégase este patrón para instanciar os DAOs.

Vantaxes do patrón DAO
----------------------

* Os obxectos non necesitan coñecer a maneira directa o destino nin a maneira na que se manipula a información.
* Baixase o nivel de acoplamento entre as clases, reducindo a complexidade de realizar cambios.
* Íllase as conexións a fonte de datos nunha capa doadamente identificable e mantible.

Véxase tamén
------------

### Ligazóns externas

* Core J2EE Patterns - Data Access Object Oracle.com *(en inglés)*.
* Core J2EE Patterns
* El Patrón DAO *(en castelán)*.
* Patrón de diseño DAO *(en castelán)*.

|  |  |
| --- | --- |
| Control de autoridades | 
* Wd: Q741137
* MAG: 41053665

 |