2

I would like your feedback regarding some best practices on design relationship between objects, specially when a singleton object is involved.

Let's imagine I need to simulate a Shop with Customers.

There is only one Shop in my application and a Customer belong only to that Shop.

When the Shop closes I need to notify each Customer.

Below some pseudo code.

In both approaches I consider a Shop as a single object.

In approach 01, I call addCustomer on shop.

In approach 02, I call addCustomer when actually creating a Customer object keeping a reference on Shop in every Customer.

I believe a third approach could be also possible, basically where shop and Customer communicate with events. So for example when creating a Customer, an event is broadcasted, shop listen to that event and add a Customer to itself.

What are your opinions, pro/cons regarding these approaches? I am using JavaScript as language. Thanks in advance for your support.

  // 01 approch
            var shop = {
                customers: [],
                addCustomer: function (customer) {
                    this.customers.push(customer);
                },
                close: function () {
                    this.customers.forEach(function (customer) {
                        customer.goOut();
                    });

                }
            };
            function Customer(name) {
                this.name = name;
                this.goOut = function () {
                    console.log(this.name + ' goes out')
                }
            }
            // set up
            shop.addCustomer(new Customer('a'));
            shop.addCustomer(new Customer('b'));
            shop.addCustomer(new Customer('c'));
            shop.close();
            console.log('-------------------------');

        // 02 approch
        var shop2 = {
            customers: [],
            addCustomer: function (customer) {
                this.customers.push(customer);
            },
            close: function () {
                this.customers.forEach(function (customer) {
                    customer.goOut();
                });
                this.customers = [];
            }
        };

        function Customer2(name) {
            this.shop = shop2;
            this.name = name;
            this.goOut = function () {
                console.log(this.name + ' goes out')
            }
            this.shop.addCustomer(this); // make sense?
        }
        new Customer2('d');
        new Customer2('e');
        new Customer2('f');
        shop2.close();
  • what does "single tone" mean? singleton? – gnat Oct 15 '15 at 11:19
  • 2
    You first option is the best. Why? Because as in real-life, it's the shop that contains the one and only copy of customers. It's also the shop that notifies each customer. Following the one-time-one-place principal is always best. The shop then, is responsible for knowing what customers are in store and notifying them of an action. – John Peters Oct 15 '15 at 13:13
  • @JohnPeters thanks for your comments, what do you think about the third approach? – GibboK Oct 15 '15 at 13:29
  • 1
    Events are the implementation of the Observer pattern and are always extremely powerful. The reason is that the Listener can operate as normal only acting when an inbound event is sent. This is especially powerful when you are talking about multiple threads each communicating with each other. Finally a newer framework exists equally or even more powerful than events known as ReactiveExtensions (RX). RX is a super-Observer implementation and takes push notifications to a new level. – John Peters Oct 15 '15 at 13:46
2

It is difficult to recommend anything in particular because we are discussing only small amount of code. But there are some comments

In approach 01, I call addCustomer on shop.

In this case shop knows about customers. Customers doesn't know about shop. So, there is a one link.

In approach 02, I call addCustomer when actually creating a Customer object keeping a reference on Shop in every Customer.

In this case both shop knows about customers and customers know about shop. So, there are two links and the coupling between classes becomes even stronger (which is mostly bad)

I believe a third approach could be also possible, basically where shop and Customer communicate with events.

This relaxes the coupling somewhat, but does not remove it anyway.

For my understanding coupling should be removed as Shop is not referenced in ? Customer as in the second approach. Am I wrong?

Well, will it be removed or not depends on what exactly you do when event is received. Coupling is just knowledge. If after event is received, customer adds itself to the shop or stores inside itself a reference to the shop, coupling is still there.

There is also an indirect coupling. You are sending an event and this event is processed. It might be processed without involving actual object reference, but it is still there. Your system imposes knowledge about relation between these two classes.

So, you must give objects minimum knowledge about each other. But not less knowledge, that is required for them to function correctly.

  • Regarding your latest point (third approach), I understand your point on "relaxes the coupling" but what do you mean by "does not remove it anyway"?. For my understanding coupling should be removed as Shop is not referenced in Customer as in the second approach. Am I wrong? Thanks again for your time on this. – GibboK Oct 15 '15 at 13:34
0

The classical pattern you could use to implement this is the observer pattern. It's the abstraction of your first solution basically. With the observer pattern it doesn't matter to your shop, which type of objects are listening to your "close-event". So that could be customers but also suppliers (well ..whatever you can think of :) ).

See those links as a starting point:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.