"Refactoring – Improving the design of existing code" reading notes----change Value to Reference

Source: Internet
Author: User

Sometimes you think that an object should be the only thing that's going to be global, which is the concept of reference (Reference). It means that when you modify him at a certain location, all the objects that are shared with him should be modified when they visit him again. And not as a value object, not modifiable. For example, you know Xiao Ming, I also know Xiao Ming, Xiao Ming suddenly kicked the hair, this time you know Xiao Ming and I know xiaoming are the same person, are bald, this is the only example of the world, however, you have 100 dollars, I have 50 yuan, I put 50 dollars spent only 20, The 100 dollars you have in your hand will not change because of my 50 dollars change, and will not be modified accordingly, this is the value object. In C + + code, for the concept of reference, we can refer to the example of the previous article

void Setcustomer (const QString &value) {    delete m_customer;     = NULL;     New Customer (value);}

In order for my m_customer to produce the concept of "value object", I recreate it every time I make a set, which ensures that my object is not modifiable and that the properties of the value object are ensured. To summarize, reference objects are like "clients", "accounts", and each object represents a real-world thing. You can directly use "= =" to compare the two objects are equal, and the value object is more like "date", "money" such things, you do not have to worry about its existence, perhaps there are hundreds of thousands of 100 yuan in the system of the object, but it is not related to you, of course, if you want to do the comparison, You can also overload the "= =" to make comparisons.

This also creates a dilemma between the reference object and the value object. Sometimes you start with a simple value object, where you save a small amount of non-modifiable data, and then you might want to add some modifiable data to the object and make sure that any modification to any object affects all references to that object . At this point you should consider turning this object into a reference object.

Practice:

    • Use the Replace Constructor with Factory Method.
    • Compile, test.
    • Decide what object is responsible for providing access to new objects. May be a static dictionary or a registry object, you can also use multiple objects as access points for new objects.
    • Decide whether these reference objects should be created in advance or should be created dynamically. If these reference objects are pre-created and you have to read them out of memory, make sure they are loaded in time when they are needed.
    • Modify the factory function so that it returns a reference object. If the object is pre-created, you need to think about how to handle the error in case someone wants an object that doesn't actually exist. You might want to use the rename Method for the factory function to convey this information, which returns a saved object.
    • Compile, test.

Example:

classcustomer{ Public: Customer (ConstQString &name): M_name (name) {} QString name ()Const        {            returnM_name; }    Private:        ConstQString m_name;};classorder{ Public: Order (ConstQString &customerName): M_customer (NewCustomer (CustomerName)) {        }        voidSetcustomer (ConstQString &customerName)            {Delete M_customer; M_customer=NULL; M_customer=NewCustomer (customerName); } QString customerName ()Const        {            returnM_customer->name (); }    Private: Customer*M_customer;};

We quoted the Replace Data Value with object as an example, and we said in the previous section that refactoring didn't end there, and that's the next step. We have the customer class, we can see that he is being used by the order class, and the principle is "value object", we can see the client code as follows

 static  int  numberoforderfor (const  qlist<order> &orders, const  QString &customername) { int  result = 0  Span style= "color: #000000;"    >;  foreach   (order order, orders) {if  (Order.customername () == CustomerName) {        Result  ++; }}  return   result;}  

To the current location, customer is also a value object, which results in even if multiple orders belong to one customer, but this one customer is their own for each order. We want to change this situation and hope to make customers the only person in the world. That is, to allow these orders to share the same customer object, it means that each customer should only correspond to one of the customers.

First we use the Replace Constructor with Factory Method to control the creation of the customer object, which is very important later, and we define the factory function in the customer class.

class customer{    public:        static Customer *create (const QString & name)        {            returnnew  Customer (name);}        };

Then change the place where the constructor was originally called to call the factory function.

class order{    public:        Order (const QString &customerName)        {            = customer::create (customerName);        }};

We then declare the original customer's constructor function as private.

class customer{    private:        Customer (const QString &  CustomerName)        {            = name;        }};

Now that we need to decide how to access these unique customer objects, the author prefers to access it through one of the fields in order, but in this case there is no such obvious field that can be used to access the Customer object. Usually we need to create a registry object to hold all the customer objects as an access point . To simplify our example, we keep the registry in the static of the customer class and let the customer use it as the access point.

Static Qhash<qstring, Customer *> hashtables;

After this decision we need to make the next important decision----whether it should be created at the time of the request or should be created beforehand. Here we choose the latter, in the application's startup code, we first load the customer objects that need to be used, either from the database or from the file. For the sake of simplicity, we explicitly generate these objects in our code, but we can always use Subsititute algorithm to change how they are created.

classcustomer{ Public:    Static voidloadcustomers () {NewCustomer ("Leo"),Store (); NewCustomer ("Tom"),Store (); NewCustomer ("Marry"),Store (); }    Private:    voidStore () {Hashtables.insert ( This. Name (), This); }};

Now we need to modify the factory function so that it returns to the pre-created Customer object.

Static Customer *create (const QString &name) {    return  hashtables.value (name);}

Since create always returns an existing customer object, we should use rename method to modify the name of the factory function in order to emphasize this.

class customer{    public:        static Customer *getnamed (const QString &name)        {            return  hashtables.value (name);        }};

"Refactoring – Improving the design of existing code" reading notes----change Value to Reference

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.