El patrón de diseño Factory Method (Método Fábrica) sirve para abstraer el proceso de creación de un objeto. A raíz de una clase se crearían todos los objetos con las propiedades y funciones tanto del objeto padre como de los hijos. Forma parte de los patrones de diseño creacionales.
En este ejemplo vamos a suponer que tenemos un objeto User que podrá ser de dos tipos, Normal
y Premium
. En función del tipo de usuario tendrá un estado diferente y mostrará o no anuncios.
Diagrama de flujo:
interface User { val name: String val surname: String fun getFullName() = "$name $surname" fun status(): String fun showAds(): Boolean }
Estos serían los dos tipos de usuarios con las diferentes implementaciones de las funciones.
class Normal(override val name: String, override val surname: String) : User { override fun status() = "Normal" override fun showAds() = true } class Premium(override val name: String, override val surname: String) : User { override fun status() = "Premium" override fun showAds() = false }
Para facilitar la comprobación de los diferentes usuarios, utilizaremos un Enum
llamado UserType
:
enum class UserType { Normal, Premium }
Para obtener ahora un usuario utilizaríamos la fabrica UserFactory
, la cual nos instanciará un objeto en función del tipo, del nombre y del apellido:
object UserFactory { fun getUser(userType: UserType, name: String, surname: String): User { return when (userType) { UserType.Normal -> Normal(name = name, surname = surname) UserType.Premium -> Premium(name = name, surname = surname) } } }
Aquí puedes ver como utilizar la UserFactory
y para ver el código al completo pulsa en el ‘+’ a la derecha.
fun main() { //sampleStart val normal = UserFactory.getUser(UserType.Normal, "James", "Smith") with(normal) { println(getFullName()) println(status()) println("Show ads: ${showAds()}") } val premium = UserFactory.getUser(UserType.Premium, "Peter", "Brown") with(premium) { println(getFullName()) println(status()) println("Show ads: ${showAds()}") } //sampleEnd } interface User { val name: String val surname: String fun getFullName() = "$name $surname" fun status(): String fun showAds(): Boolean } class Normal(override val name: String, override val surname: String) : User { override fun status() = "Normal" override fun showAds() = true } class Premium(override val name: String, override val surname: String) : User { override fun status() = "Premium" override fun showAds() = false } enum class UserType { Normal, Premium } object UserFactory { fun getUser(userType: UserType, name: String, surname: String): User { return when (userType) { UserType.Normal -> Normal(name = name, surname = surname) UserType.Premium -> Premium(name = name, surname = surname) } } }
Clase Main
:
public class Main { public static void main(String[] args) { User normal = UserFactory.getUser(UserType.Normal, "James", "Smith"); System.out.println(normal.getFullName()); System.out.println(normal.status()); System.out.println(String.format("Show ads: %s", normal.showAds())); User premium = UserFactory.getUser(UserType.Premium, "Peter", "Brown"); System.out.println(premium.getFullName()); System.out.println(premium.status()); System.out.println(String.format("Show ads: %s", premium.showAds())); } }
La clase Factory UserFactory
:
public class UserFactory { public static User getUser(UserType userType, String name, String surname) { switch (userType) { case Normal: return new Normal(name, surname); case Premium: return new Premium(name, surname); default: return new Normal(name, surname); } } }
La interfaz User
:
public interface User { String getFullName(); String status(); boolean showAds(); }
Enum Polygon
:
public enum UserType {Normal, Premium}
Las clases Normal
y Premium
:
public class Normal implements User { private String name; private String surname; public Normal(String name, String surname) { this.name = name; this.surname = surname; } @Override public String getFullName() { return String.format("%s %s", name, surname); } @Override public String status() { return "Normal"; } @Override public boolean showAds() { return true; } } public class Premium implements User { private String name; private String surname; public Premium(String name, String surname) { this.name = name; this.surname = surname; } @Override public String getFullName() { return String.format("%s %s", name, surname); } @Override public String status() { return "Premium"; } @Override public boolean showAds() { return false; } }
Como veis hay hacerlo en 6 archivos mientras que en Kotlin podríamos hacerlo en 1 (2 o 3 en un caso real). Eso sin contar la diferencia total de líneas.
Enlaces de interés:
En esta lección aprenderás a declarar variables y los tipos básicos.
La mejor forma de aprender algo en esta vida es a base de practicar. Espero…
La principal forma de iniciar una corrutina en Kotlin es con el coroutine builder launch…
Las coroutines en Kotlin vienen a tratar de solucionar todos los problemas y dificultades que…
Con este esquema te puedes guiar a la hora de elegir el modismo o función…
El último que queda por ver es with qué en inglés significa "con". Por lo…