No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Singleton: pros y contras

6/27
Recursos

Aportes 15

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

Hasta este punto del curso, me hubiese gustado profundizar más en diferentes casos de uso que pudiese tener el Patrón Singleton en desarrollo de software, pues de esta manera es como se podría interiorizar el concepto de mejor forma.

Gracias.

Les dejo mi codigo en TypeScript:

class Product {
  private id: number;
  private name: string;
  private cost: number;

  constructor(id: number, name: string, cost: number) {
    this.id = id;
    this.name = name;
    this.cost = cost;
  }

  getId() {
    return this.id;
  }

  getName() {
    return this.name;
  }

  getCost() {
    return this.cost;
  }
}

class ShoppingCart {
  private static instance: ShoppingCart;
  private cart: Product[] = [];

  private constructor() {}

  getCart() {
    return this.cart;
  }

  add(product: Product) {
    this.cart.push(product);
  }

  deleteById(id: number) {
    this.cart = this.cart.filter((prod) => prod.getId() !== id);
  }

  static getInstance() {
    if (!this.instance) this.instance = new ShoppingCart();
    return this.instance;
  }
}

(() => {
  const cart = ShoppingCart.getInstance();
  const cart2 = ShoppingCart.getInstance();
  const prod1 = new Product(1, "mate", 3000);
  const prod2 = new Product(2, "bombilla", 2900);
  const prod3 = new Product(3, "matera", 2400);

  // agregamos products al cart
  cart.add(prod1);
  cart.add(prod2);
  cart.add(prod3);

  console.log(cart.getCart());

  // borramos por id
  cart.deleteById(2);

  console.log(cart.getCart());

  // verificamos que ambos cart tienen la misma instancia, por tanto ambos tienen los mismos products
  console.log(cart === cart2);
  console.log(cart.getCart());
  console.log(cart2.getCart());
})();

Usen ChatGPT o Bard de google para solicitarle casos de uso reales, eso me ayudo a entender mejor.

I think this should do it:

class ShoppingCart {
    static instance = undefined;

    constructor() {
        this.products = [];
    }

    getProducts = () => {
        return this.products;
    }

    addProduct = (product) => {
        return this.products.push(product);
    }

    deleteProductById = (id) => {
        return this.products = this.products.filter((product) => product.id !== id);
    }

    static getInstance = () => {
        if (!ShoppingCart.instance) ShoppingCart.instance = new ShoppingCart()
        return ShoppingCart.instance;
    }
}

class Product {
    constructor(id, name, cost) {
        this.id = id;
        this.name = name;
        this.cost = cost;
    }
    getID() {
        return this.id;
    }
    getName() {
        return this.name;
    }
    getCost() {
        return this.cost;
    }
}

const ClientApp = () => {
    const cart = ShoppingCart.getInstance();
    const vasos = new Product(1205, 'paquete de vasos', 12000);
    const zapatos = new Product(2166, 'zapatos - par', 57600)
    console.log(vasos.getName(), vasos.getCost(), vasos.getID());
    // Agregamos productos al carrito. 
    cart.addProduct(vasos);
    console.log('Agregamos vasos al cart', cart.getProducts());

    // confirmamos que el cart es el mismo, aún en otra instancia. 
    const cart2 = ShoppingCart.getInstance();
    cart2.addProduct(zapatos);
    console.log('Probamos que el nuevo cart también tiene productos', cart2.getProducts());

    // Borramos el producto y probamos en ambos carritos. 
    cart.deleteProductById(1205);
    console.log('Eliminamos vasos del cart', cart.getProducts(), cart2.getProducts());
}

ClientApp();

Mi sulocion Ts

class Product {
    private id: number;
    private name: string;
    private cost: number;

    constructor(id: number, name: string, cost: number) {
        this.id = id;
        this.name = name;
        this.cost = cost;
    }

    getid(): number {
        return this.id;
    };

    getName(): string {
        return this.name;
    };

    getCost(): number {
        return this.cost;
    };
};

class ShoppingCar {
    private static instance: ShoppingCar;
    private products: Product[];

    private constructor() {
        this.products = [];
    }

    static getInstance(): ShoppingCar {
        if (!ShoppingCar.instance) {
            ShoppingCar.instance = new ShoppingCar;
        }
        return ShoppingCar.instance;
    }

    addProduct(...product: Product[]) {
        this.products.push(...product)
    }

    getProducts(): Product[] {
        return this.products;
    }

    deleteById(id: number) {
        return this.products = this.products.filter(elem => elem.getid() !== id);
    }

}

// implementacion 
// crear una unica instancia de shopping car
const car = ShoppingCar.getInstance();
const car2 = ShoppingCar.getInstance();

// crear 2 products para poblar
let product1 = new Product(1, 'amp', 1500);
let product2 = new Product(2, 'guitar', 1700);

car.addProduct(product1, product2)

// comprobaciones en consola
console.log(`shold be true, ${car === car2}`);
console.log(car.getProducts());




Mi código de TS 👍:

class Product {
    private id: number;
    private name: string;
    private price: number;

    constructor(id: number, name: string, price: number) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    setId(id: number) {
        this.id = id;
    }

    setName(name: string) {
        this.name = name;
    }

    setPrice(price: number) {
        this.price = price;
    }

    getId() {
        return this.id;
    }

    getName() {
        return this.name;
    }

    getPrice() {
        return this.price;
    }
}

/* 
    We create our singleton class, the idea behind having one, is that therere never 2 of these.
    Just one per app or client
*/
class ShoppingCart {
    private static instance: ShoppingCart;
    private products: Product[] = [];

    private constructor() {}

    static getInstance() {
        if(!ShoppingCart.instance) {
            ShoppingCart.instance = new ShoppingCart();
        }
        return ShoppingCart.instance;
    }

    setCart(products: Product[]) {
        this.products = products;
    }

    getCart() {
        return this.products;
    }

    add(product: Product) {
        this.products.push(product);
    }

    addGroup(products: Product[]) {
        // pushes each element of the array 
        products.forEach(prod => this.products.push(prod));
    }

    remove(id: number) {
        this.products = this.products.filter((product) => product.getId() !== id);
    }
}

function app() {
    const cart1 = ShoppingCart.getInstance();
    const cart2 = ShoppingCart.getInstance();

    const products: Product[] = [
        new Product(1, "Dónde", 100),
        new Product(2, "está", 200),
        new Product(3, "Dios", 300)
    ];

    cart1.addGroup(products);
    cart1.remove(1);

    // We never added anything to cart2, but it has the same instance as cart1,
    // so both are equals
    console.log(cart1 === cart2); // true
}

app();
class Product {
    private id: number
    private name: string
    private cost: number

    public constructor(id: number, name: string, cost: number) {
        this.id = id
        this.name = name
        this.cost = cost
    }

    public getName(): string {
        return this.name
    }

    public getCost(): number {
        return this.cost
    }
    
    public getId(): number {
        return this.id
    }
}

class ShoppingCart {
    private static instance: undefined | ShoppingCart
    private products: Product[]
    
    private constructor() {
        this.products = []
    }

    public add(product: Product): void {
        this.products.push(product)
    }

    public deleteById(id: number): void {
        this.products = this.products.filter(product => product.getId() !== id)
    }

    public getProducts(): Product[] {
        return this.products
    }

    public static getInstance(): ShoppingCart {
        if(!ShoppingCart.instance) ShoppingCart.instance = new ShoppingCart()

        return ShoppingCart.instance
    }
}

function clientApp() {
    const silla = new Product(1, 'Silla de oficina', 10000)
    const mesa = new Product(2, 'Mesa para oficina', 20000)
    const lampara = new Product(3, 'Lampara de oficina', 5000)

    const shoppingCart = ShoppingCart.getInstance()

    // agregamos los productos al carrito
    shoppingCart.add(silla)
    shoppingCart.add(mesa)
    shoppingCart.add(lampara)

    console.log(shoppingCart.getProducts())

    // eliminamos un producto
    shoppingCart.deleteById(mesa.getId())

    console.log(shoppingCart.getProducts())
}

clientApp()

Buenas! Dejo mi implementación en Python

class Product:

    def __init__(self, id, name, cost):
        self._id = id
        self._name = name
        self._cost = cost

    def get_name(self):
        return self._name

    def get_cost(self):
        return self._cost
    
    def get_id(self):
        return self._id

class ShoppingCar:

    _instance = None
    _products = []

    def __new__(cls):
        if not cls._instance:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def add_product(self, product):
        self._products.append(product)

    def delete_by_id(self,id):
        for elemento in self._products:
            if elemento['id'] == id:
                self._products.remove(elemento)
    def show_products(self):
        return self._products

    @staticmethod
    def get_instance():
        return ShoppingCar()

class ClientApp:
    def __init__(self, id):
        self.id = id
        self.shopping_car = ShoppingCar.get_instance()

client = ClientApp(1)
client_2 = ClientApp(2)
print(client.shopping_car , client_2.shopping_car, client.shopping_car == client_2.shopping_car) # True
client.shopping_car.add_product(Product(1,'chocolate',22))

print(client.shopping_car == client_2.shopping_car, '#######')

Hola, comparto mi solución, pense primero en usar .findIndex() y luego .splice() para el deleteById, aunque note en los comentarios que la mayoria usaron .filter():

class Product {
    private _id: number;
    private _name: string;
    private _cost: number;

    constructor(id: number, name: string, cost: number) {
        this._id = id;
        this._name = name;
        this._cost = cost;
    }

    get id() {
        return this._id;
    }
    get name() {
        return this._name;
    }
    get cost() {
        return this._cost;
    }
}

class ShoppingCar {
    private static instance: ShoppingCar;
    private _products: Array<Product>;

    private constructor() {
        this._products = [];
    }

    public static getInstance(): ShoppingCar {
        if (!ShoppingCar.instance) {
            ShoppingCar.instance = new ShoppingCar();
        }
        return ShoppingCar.instance;
    }

    get products() {
        return this._products;
    }

    add(product: Product): void {
        this._products.push(product);
    }
    deleteById(id: number): void {
        const index = this._products.findIndex(product => product.id === id);
        if (index !== -1) this._products.splice(index, 1);
        else console.log("producto no encontrado");
    }
}

function clientApp() {
    const shoppingCar = ShoppingCar.getInstance();

    shoppingCar.add(new Product(1, "Collar Dorado", 200));
    shoppingCar.add(new Product(3, "Silla", 250));
    shoppingCar.add(new Product(2, "Vaso", 50));

    console.log(shoppingCar.products);

    shoppingCar.deleteById(1);
    shoppingCar.deleteById(1);

    console.log(shoppingCar.products);

    const shoppingCar2 = ShoppingCar.getInstance();
    console.log(shoppingCar === shoppingCar2);
}

clientApp();

I just want to share my solution in TS: ```ts class ShoppingCart { private static instance: ShoppingCart; private cart: Product[] = []; private constructor() {} static getInstance(): ShoppingCart { if (!ShoppingCart.instance) { ShoppingCart.instance = new ShoppingCart(); } return ShoppingCart.instance; } public getCart(): Product[] { return this.cart; } public addProduct(product: Product): void { this.cart.push(product); } public deleteById(id: number): void { let indexProduct = this.cart.findIndex((item) => item.getId() == id); this.cart.splice(indexProduct, 1); } } class Product { private id: number; private name: string; private cost: number; public constructor(id: number, name: string, cost: number) { this.id = id; this.name = name; this.cost = cost; } public getId(): number { return this.id; } public getName(): string { return this.name; } public getCost(): number { return this.cost; } } (() => { const cart = ShoppingCart.getInstance(); const cart2 = ShoppingCart.getInstance(); const p1 = new Product(1, "camara", 500); const p2 = new Product(2, "cama", 1500); const p3 = new Product(3, "cojin", 20); cart.addProduct(p1); cart.addProduct(p2); cart.addProduct(p3); console.log(cart.getCart()); cart.deleteById(2); console.log(cart.getCart()); // Verify the instance is the same in both carts console.log(cart === cart2); console.log(cart.getCart()); console.log(cart2.getCart()); })(); ```class ShoppingCart {  private static instance: ShoppingCart;  private cart: Product\[] = \[];   private constructor() {}   static getInstance(): ShoppingCart {    if (!ShoppingCart.instance) {      ShoppingCart.instance = new ShoppingCart();    }    return ShoppingCart.instance;  }  public getCart(): Product\[] {    return this.cart;  }  public addProduct(product: Product): void {    this.cart.push(product);  }  public deleteById(id: number): void {    let indexProduct = this.cart.findIndex((item) => item.getId() == id);    this.cart.splice(indexProduct, 1);  }} class Product {  private id: number;  private name: string;  private cost: number;   public constructor(id: number, name: string, cost: number) {    this.id = id;    this.name = name;    this.cost = cost;  }  public getId(): number {    return this.id;  }  public getName(): string {    return this.name;  }  public getCost(): number {    return this.cost;  }} (() => {  const cart = ShoppingCart.getInstance();  const cart2 = ShoppingCart.getInstance();  const p1 = new Product(1, "camara", 500);  const p2 = new Product(2, "cama", 1500);  const p3 = new Product(3, "cojin", 20);   cart.addProduct(p1);  cart.addProduct(p2);  cart.addProduct(p3);   console.log(cart.getCart());   cart.deleteById(2);   console.log(cart.getCart());  // Verify the instance is the same in both carts  console.log(cart === cart2);  console.log(cart.getCart());  console.log(cart2.getCart());})();
Esta version implementa un carrito diferente para cada usuario, utilizando el patron singleton: ```js const PRODUCTS: Product[] = [ { name: "apple", id: 1, cost: 2000 }, { name: "banana", id: 2, cost: 500 }, { name: "coconut", id: 3, cost: 3000 }, { name: "meat", id: 4, cost: 20000 }, { name: "pineapple", id: 5, cost: 1000 }, { name: "coke", id: 6, cost: 1800 }, ] as Product[]; interface Product { id: number; name: string; cost: number; getName(): string; getCost(): number; getId(): number; } interface cart { add(product: Product): void; deleteById(id: number): void; getInstance(client: string): ShoppingCart; } class ShoppingCart implements cart { private products: Product[] = []; private constructor() {} static usersCarts: Record<string, ShoppingCart> = {}; static getInstance(client: string): ShoppingCart { return this.usersCarts[client] ? this.usersCarts[client] : new ShoppingCart(); } add(product: Product): void { this.products.push(product); } deleteById(id: number): void { const productIndex = this.products.findIndex( (product) => product.id === id ); if (productIndex !== -1) { this.products.splice(productIndex, 1); } } getTotal(): number { return this.products.reduce((total, product) => total + product.cost, 0); } } function clientApp() { const cartUser1 = ShoppingCart.getInstance("Client_1"); const cartUser2 = ShoppingCart.getInstance("Client_2"); const cartUser3 = ShoppingCart.getInstance("Client_3"); cartUser1.add(PRODUCTS[0]); cartUser1.add(PRODUCTS[1]); cartUser2.add(PRODUCTS[2]); cartUser2.add(PRODUCTS[3]); cartUser3.add(PRODUCTS[4]); cartUser3.add(PRODUCTS[5]); // Display the cart contents and total cost for each user console.info("Cart Contents and Total Cost for Each User:"); console.log("Client 1 Cart:"); console.log("Cart Contents:", cartUser1); console.log("Total Cost:", cartUser1.getTotal()); console.log("Client 2 Cart:"); console.log("Cart Contents:", cartUser2); console.log("Total Cost:", cartUser2.getTotal()); console.log("Client 3 Cart:"); console.log("Cart Contents:", cartUser3); console.log("Total Cost:", cartUser3.getTotal()); cartUser1.deleteById(PRODUCTS[0].id); cartUser2.deleteById(PRODUCTS[2].id); cartUser3.deleteById(PRODUCTS[4].id); // Display the updated cart contents and total cost for each user console.info("Cart Contents and Total Cost After Deletion for Each User:"); console.log("Client 1 Cart:"); console.log("Cart Contents:", cartUser1); console.log("Total Cost:", cartUser1.getTotal()); console.log("Client 2 Cart:"); console.log("Cart Contents:", cartUser2); console.log("Total Cost:", cartUser2.getTotal()); console.log("Client 3 Cart:"); console.log("Cart Contents:", cartUser3); console.log("Total Cost:", cartUser3.getTotal()); } clientApp(); ```

Haciendo privada las propiedades de Product, es la forma en la que se me ocurrió después acceder a ellas mediante ShoppingCar.

class ShoppingCar{
    static #instanceSC = undefined;
    #products = [];
    
    addProduct(product){
        this.#products.push(product);
    }
    getProducts(){
        return this.#products;
    }

    deleteById(id){
        for (let n = 0; n < this.#products.length; n++) {
            if (this.#products[n].id === id) {
                this.#products.splice(n, 1);
                break; // Si los IDs son únicos, puedes salir del bucle una vez encontrado
            }
        }
        return this.#products;
    }
    static getInstance(){
        if(!ShoppingCar.#instanceSC){
            ShoppingCar.#instanceSC = new ShoppingCar();
        }
        return ShoppingCar.#instanceSC;
    }
}

class Product{
    #id;
    #name;
    #cost;

    constructor(id, name, cost) {
        this.#id = id;
        this.#name = name;
        this.#cost = cost;
    }

    getName() {
        return this.#name;
    }

    getCost() {
        return this.#cost;
    }

    getId() {
        return this.#id;
    }
}

const myShoppingCart = ShoppingCar.getInstance();
const myProduct = new Product(1, 'kevin', 100000);

myShoppingCart.addProduct(myProduct);

const products = myShoppingCart.getProducts();
products.forEach(product => {
    console.log(`ID: ${product.getId()}, Name: ${product.getName()}, Cost: ${product.getCost()}`);
});

El concepto de “un solo punto de acceso global” también es conocido como Single Source of Truth (única fuente de verdad).

¡Hola!

Dejé mi solución al reto en TypeScript y en Java en mi repositorio en GitHub, también dejé un tutorial con el link al repositorio, pero para este reto en Java, se encuentra aquí.

Les dejo como implemente el codigo del reto, espero sus feedback

Class Product

class Product {
    constructor(id, name, cost) {
        this._id = id;
        this._name = name;
        this._cost = cost;
    }
    getName() {
        return this._name;
    }
    getCost() {
        return this._cost;
        }
    getId() {
        return this._id;
    }
}

Class ShoppingCar

class ShoppingCar {
    static instance = undefined

    constructor() {
        this._products = []
    }

    static getInstance() {
        if(!ShoppingCar.instance) {
            ShoppingCar.instance = new ShoppingCar()
        }
        return ShoppingCar.instance
    }

    addProduct(product) {
        this._products.push(product)        
    }
    getProductById(id) {
        return this._products.find(product => product._id === id)
    }
    getProductByName(name) {
        return this._products.filter(product => product._name === name)
    }
    setProduct(newProductList) {
        this._products = newProductList
    }
    deleteProduct(id) {
        const deletedProduct = this.getProductById(id)
        const newProductList = this._products.filter(product => product._id !== id)
        this.setProduct(newProductList)
        return deletedProduct._name
    }
    getAllProduct() {
        return this._products
    }    
}

Cliente App para probar el funcionamiento del codigo

(function clienteApp() {
    const cart = ShoppingCar.getInstance();
    const vasos = new Product(1, "vasos plasticos" , 3)
    const zapatos = new Product(2, "gomas deportivas" , 30)
    const franela = new Product(3, "franela azul" , 25)
    const gorra = new Product(4, "gorra americana" , 10)
    const shorts = new Product(5, "shorts rojos" , 15)    

    cart.addProduct(vasos)
    cart.addProduct(zapatos)
    cart.addProduct(franela)
    cart.addProduct(gorra)
    /* Validamos que hay productos en el carrito */
    console.log(cart.getAllProduct);
    
    /* Instanciamos un segundo carrito y validamos que ya tiene productos*/
    const cart2 = ShoppingCar.getInstance();
    console.log(cart2.getAllProduct);
    /* Le agregamos un producto */
    cart2.addProduct(shorts);
    console.log(cart2.getAllProduct())
    /* Eliminamos un producto */
    console.log('Eliminamos exitosament el producto', cart.deleteProduct(2))

    /* Validamos que se elimino en ambos carritos */    
    console.log(cart.getAllProduct(),)
    console.log(cart2.getAllProduct())
})()