Memory manipulation is possible
5.5 Static and dynamic classification
So far we have assumed that an object does not change its class affiliation during its entire existence. The relationship between an object and its class could not be changed - the classification of the object was static.
Change of class affiliation
However: Sometimes in practice we have scenarios in which the class membership of an object changes during its existence. A prospective customer can become a customer or an external consultant can become an internal employee. In such cases we speak of a dynamic classification.
The dynamic classification mostly plays a role in the conceptual models, in programming it is seen less often. One reason for this will probably be the fact that the class-based programming languages such as Java, C #, C ++, Python or Ruby do not support them. [In C ++ the class membership of a polymorphic object is realized by the pointer to the table of its virtual methods. With direct memory manipulation it is therefore possible to dynamically change the class membership of an object in C ++. However, it is a daring game with fire to do something like this. Games with fire are exciting and interesting, and those who like them should consider a career as a stuntman or circus performer rather than a software developer. ]
5.5.1 Dynamic change of class membership
However, there are also languages that explicitly support a change in class membership. One of these languages is the Common Lisp Object System, CLOS. We will therefore first use the example of CLOS to show how we could make such an adaptation of the class membership if the language supports it. Then we will show how we can implement a corresponding mechanism by using strategies in the more common languages such as Java.
In a language such as CLOS, mechanisms are provided that allow the type of an object to be changed in a defined way during the runtime of a program.
We turn an A into a B.
If we make object x (an instance of class A) an instance of class B, all attributes that appear in A and B are taken over. In addition, an update-instance-for-different-class method is called (if available) in which data elements to be newly initialized that are defined in B but are not provided by A can be assigned values. The rest is simple, since x is now an instance of B, the corresponding calls to operations are also assigned to B's methods.
Business partners: guests, interested parties and customers
As an example, let's take an application in which business partners are classified as guests, prospects, or customers. In doing so, they can turn from guest to prospect and ultimately to customers. The corresponding hierarchy is shown in Figure 5.70.
Figure 5.70Business partner hierarchy
The definition of the classes in CLOS then looks like below.
Listing 5.33Definition of a class hierarchy in CLOS
All classes involved have different implementations of the display operation. Since further attributes are also added in the specific classes, the representation of a business partner is different in all derived classes.
Listing 5.34Different presentations for business partners
Guest becomes a prospect.
Now we want to output the description of copies of the respective classes. In doing so, we simply let a guest change his class to interested. This is done in CLOS using the change-class method.
We get the following output from the interpreter:
Presetting of new attributes
Oops, we promoted Frieda Müller from guest to prospect, but without giving her a value for the required attribute expected sales. This means that when a class is changed, special new initializations are necessary for an object. CLOS provides the generic function update-instance-for-different-class for this.
If we override the method as listed above, it will be called when an object changes from the guest class to the interested class. Our output then looks like this:
We can do that. Shall we too?
Although the programming language here provides simple and intuitive mechanisms for making an object change class, such a procedure can increase the complexity of programs. Even if a programming language allows such an approach: It is usually better to use the strategy design pattern. This can also be used in languages that do not support dynamic classification.
There is also a fundamental conceptual problem when changing the class assignment at runtime. As with any other change to an object, if we change its class, we must ensure that the object continues to fulfill all the promises it has made. The principle of substitutability requires just that.
What does that mean? In the statically typed programming languages, the class affiliation determines the type of the object. The class affiliation thus determines whether a variable can contain or reference the object. If the object's class membership changes, we must ensure that only those variables reference the object that are compatible with its new type.
But there is a way to ensure this and still achieve the desired change in behavior. You have to ensure that the variables can only have as their type a superclass of all possible classes to which the object can mutate in the course of its existence.
The real class affiliation of the object must therefore not be visible, only its class affiliation to a superclass can be known. And this does not change. Only the subtype of the object, which is invisible from the outside, changes. The object doesn't change its interface, it just changes the implementation.
In the following section we will see how we can achieve exactly this behavior by applying the "strategy" design pattern.
5.5.2 "Strategy" design pattern instead of dynamic classification
If the externally visible class membership of an object does not change, the change in the actual class membership can also be implemented in a programming language that does not support dynamic classification.
The method of choice in this case is the "strategy" design pattern.
|"Strategy" design pattern|
If part of the behavior of the instances of a class can change depending on their state, the different behaviors can be moved to separate strategy classes.
Each instance of the main class has an instance of one of the strategy classes at any point in time, to which it delegates the implementation of its behavior. If the state of the object changes in such a way that a change in behavior is necessary, the object exchanges its strategy object. By using this pattern, one decouples the different behavior variants of the specimens in the main class without having to resort to dynamic classification.
Let's pick up a slightly modified version of our example from Figure 5.70 and assume we are writing an e-commerce Internet application.
Visitors to our site can register and order goods. The content of the page is specially prepared for each user. Users who have not yet ordered are presented with different advertising and promotions than existing customers. New customers can only pay in advance, premium customers are offered installment payments. The membership of each user in these categories can change over time.
One possible implementation is a User class, which knows the current status of the user and evaluates it in its methods. Listing 5.35 shows a Java implementation of such a class.
Listing 5.35Problematic solution: Evaluation of customer status in the »User« class
We have to assume that such switch commands appear not only in the displayAds method, but in many other methods of the User class. This is not particularly clear and leads to a lot of effort if the categorization of the visitors changes.
In the future, we could assign certain customers who like to order but are reluctant to pay to a new category, which should cause the website to behave in a new way. This would mean that we would have to sift through and adjust many methods and many switch commands.
Figure 5.71 shows one way to solve this problem by using the "strategy" design pattern.
Figure 5.71"Strategy" design pattern applied
Our application becomes clearer if we place the behavior of the different user categories in different classes - in strategy classes such as ProspectStrategy and NewCustomerStrategy. In Section 5.4.2 we described the concept of delegation. Policy class instances are objects to which the invocation of operations is delegated. In addition, we can exchange these objects at defined times in order to change the behavior of an object.
If you apply the "strategy" pattern to our example, each instance of the User class has exactly one instance of one of the subclasses of UserStrategy at any given time and delegates the calls for the status-specific operations to the strategy object.
If the status of the user changes, for example a prospect becomes a new customer, the user object receives a new strategy object. This changes its behavior, but the type of the user object does not change externally.
Example of strategy classes
Listing 5.36 shows the implementation of this concept for our example in Java.
Listing 5.36Implementation of strategies for customers
On the one hand, the respective strategy determines which advertisements the customer gets to see by implementing the displayAds operation. On the other hand, through the implementation of the makePurchase operation, it also determines how an order is to be handled. The makePurchase operation can also result in a customer being promoted from prospect to customer. The makePurchase method of the ProspectStrategy class therefore returns a new strategy object that will then be used in the future. ProspectStrategy practically replaces itself, very unselfishly.
The design pattern presented here is particularly suitable for all cases in which you want to change the behavior of instances of a class at runtime.
How did you like the Openbook? We always look forward to your feedback. Please send us your feedback as an e-mail to [email protected]
- What are Queen Elizabeth's political leanings
- Casinos will ever close
- What are some arguments against gun ownership
- Is western culture successful
- How do I use SMS
- How do I find jewelry manufacturers
- House Lannister is wrongly hated
- Who will benefit when the UK leaves the EU?
- Have you ever had sex in nature?
- How can I send money without PayPal
- Practice giving blowjobs to women
- How do I unsubscribe from all emails
- Who is Anta at CodeChef
- How much does a McDonalds franchise cost
- Is the fabric of spacetime elastic?
- What are some things that money can't buy
- How can you deal with a controlling woman
- What are your good and bad habits
- Can the president carry a gun?
- What is the least interesting city
- Is Azerbaijan a fully developed country
- Where is male chastity to be found
- Why were holidays stolen from the Gentiles?
- Why is a shadow always black 1