47
Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility Summary prepared by Kirk Scott 1

Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

  • Upload
    damali

  • View
    55

  • Download
    0

Embed Size (px)

DESCRIPTION

Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility. Summary prepared by Kirk Scott. Introducing Responsibility. The topic of responsibility in design patterns can be very briefly summarized as: “Which class implements which functionality?” - PowerPoint PPT Presentation

Citation preview

Page 1: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

1

Design Patterns in JavaPart II

Responsibility PatternsChapter 7

Introducing Responsibility

Summary prepared by Kirk Scott

Page 2: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

2

Introducing Responsibility

• The topic of responsibility in design patterns can be very briefly summarized as:

• “Which class implements which functionality?”• When considered as part of the relationships between

classes, responsibility has this additional connotation:• “Is one class in the position of receiving messages

requesting some action, and also in the position of passing requests on and delegating the performance of the actions to other classes?”

Page 3: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

3

• A basic default baseline is that objects are independent and self-sufficient

• The responsibility design patterns tend to cover cases which diverge from the default

• There are patterns which embody the following, rather generally stated characteristics

Page 4: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

4

• Responsibility for performing a given action may be centralized (passing a request to a central class/object for performance)

• Responsibility for performing a given action may be escalated (passing a request up a hierarchy)

• A given object may be isolated, limiting its responsibility (implicitly putting responsibility elsewhere)

Page 5: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

5

• Responsibility turns out to be part of a much broader question of object-oriented design

• It comes back to the fundamental question of what classes should be in a design and which functionalities should be in which classes

• The book takes the attitude that programmers develop an intuitive feeling for this, but probably can’t express it very clearly

• It pursues this idea with a few challenges

Page 6: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

6

• Challenge 7.1• The class structure shown in Figure 7.1 has at least ten

questionable assignments of responsibility. Circle as many problems as you can find; then write a statement about what is wrong for four of these points.

• Comment mode on:• Some of the problems would only be evident to

someone who knew the problem domain.• Others are so gross and weird that the only reaction

might be, “Huh?”

Page 7: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

7

Page 8: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

8

Solution7.1

• The Rocket.thrust() method returns a Rocket instead of some type of number or physical quantity.

• The LiquidRocket class has a getLocation() method, although nothing in the diagram or in the problem domain suggests that we model rockets as having a location. Even if we did, there is no reason for liquid-fueled rockets, but not other Rocket objects, to have a location

Page 9: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

9

• The isLiquid() method may be an acceptable alternative to using the instanceof operator, but then we’d expect the superclass to also have an isLiquid() method that would return false.

• CheapRockets is plural, although class names are conventionally singular.

Page 10: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

10

• The CheapRockets class implements Runnable, although this interface has nothing to do with cheap rocket objects from the problem domain.

• We could model cheapness with attributes alone, so there is no justification for creating a class just for cheap rockets.

Page 11: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

11

• The CheapRockets class introduces a factoring that conflicts with factoring the rocket model as liquid or solid. For example, it is not clear how to model a cheap liquid rocket.

• The model shows that Firework is a subclass of LiquidRocket, implying that all firewords are liquid rockets, which is false.

Page 12: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

12

• The model shows a direct relation between reservations and types of firework, although no such relation exists in the problem domain.

• The Reservation class has its own copy of city, which it should get by delegation to a Location object.

• CheapRockets is composed of Runnable objects, which is simply bizarre.

Page 13: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

13

• End of Solution 7.1; on to the next topic• Looking at all of the bad elements of the previous design

may put you in the mood to try and define a good class design

• In order to define a design you end up needing agreement on terminology between users and developers

• The authors state that defining terms is useful if it helps people to communicate

• They warn that its usefulness decreases when it becomes a goal in itself and leads to conflict

Page 14: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

14

• Challenge 7.2• Define the qualities of an effective, useful

class.

Page 15: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

15

Solution 7.2

• The value of this challenge is not to get the right answer but rather to exercise your thinking about what makes up a good class. Consider whether your definition addresses the following points.

• A nuts-and-bolts description of a class is: “A named collection of fields that hold data values and methods that operate on those values” [Flanagan 2005, p. 71]

Page 16: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

16

• A class establishes a collection of fields; that is, it defines the attributes of an object. The attribute types are other classes, primitive data types, such as boolean and int, or interfaces.

• A class designer should be able to justify how a class’s attributes are related.

• A class should have a cohesive purpose.

Page 17: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

17

• The name of a class should reflect the meaning of the class both as a collection of attributes and with respect to the class’s behavior.

• A class must support all the behaviors it defines, as well as all those in superclasses and all methods in interfaces that the class implements. (A decision to not support a superclass or an interface method is occasionally justifiable.)

Page 18: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

18

• A class should have a justifiable relationship to its superclass.

• The name of each of a class’s methods should be a good commentary on what the method does.

Page 19: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

19

• End of Solution 7.2; on to the next topic• The last point of solution 7.2 was the

usefulness of descriptive method names• On the other hand, method names do not

always fully explain what the method does

Page 20: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

20

• Challenge 7.3• Give an example where, for good reason, the

effect of calling a method cannot be predicted from the method’s name.

• Comment mode on:• This is not really such a difficult question,

although the book provides a rather long and involved answer

Page 21: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

21

Solution 7.3

• For a change I don’t give the book’s answer in its entirety

• Three basic points are sufficient to summarize the idea

Page 22: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

22

• 1. The effect of calling a method on an object depends on what class the object is an instance of

• This is a result of dynamic binding• It may be necessary to sort through the

various implementations of a method to get a clear picture of what it does for a particular class

Page 23: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

23

• 2. The effect of calling a method on an object also depends on the state of the object

• A method may be coded in such a way that it makes use of the current values of the instance variables in order to reset those values or return a certain value

Page 24: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

24

• 3. At other times the effect of a method may not be immediately clear because the name is unfamiliar

• This can result from situations where you are using an interface developed by a different programmer

Page 25: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

25

• The assignment of responsibility among classes of a design seems to be more of an art than a science

• There are apparently many weak software designs that could be improved by better assignment of responsibility

• In general, clearly defining responsibilities for classes and methods, and correctly implementing them would be a good start towards a sound system design

Page 26: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

26

Controlling Responsibility with Visibility

• The authors point out that the responsibility for making sure classes and methods work as they should falls on the programmer

• It turns out that the implementation of responsibility hinges at least in part on encapsulation

• Closely related to the concept of encapsulation is the concept of visibility

• Visibility refers to the access modifiers (public, private, protected, package) applied to components of Java code

Page 27: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

27

• The basic idea is this:• By using access modifiers to limit visibility, you

reduce the number of things that client code can do with objects of your class

• This, in turn limits your responsibility• If everything were global, you would not be in a

position where you could responsibly offer any services

• A client could do anything at all

Page 28: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

28

This table summarizes the access modifiers in Java and their meanings

Page 29: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

29

• The authors emphasize that the descriptions in the table are informal

• It is also important to have a grasp of their formal meaning

• The authors pose an interesting question• It has to do with the level at which visibility is

applied• Is this a class level construct or an object level

construct in Java?

Page 30: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

30

• Challenge 7.4• Can an object refer to a private member of

another instance of the same class? Specifically, will the following code compile?

• Comment mode on:• See the code on the next overhead• I have fleshed out their code and modified it so

that the authors’ coding style doesn’t mislead you

Page 31: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

31

• public class Firework• {• private double weight;• public Firework(double weightIn);• {• weight = weightIn;• }• public double compare(Firework fireworkIn)• {• return this.weight – fireworkIn.weight;• }• }

Page 32: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

32

• What the book is driving at is this:• Is the expression fireworkIn.weight valid?• The method compare() would be called on an

instance of the Firework class• The explicit parameter passed in is also of the

type Firework• Within the body of the method, do you have

direct access to the private instance variable weight belonging to fireworkIn?

Page 33: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

33

• Solution 7.4• The code compiles with no problems. Access

is defined at a class level, not an object level. So, for example, one Firework object can access another Firework object’s private variables and methods.

Page 34: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

34

• Comment mode on:• Of course it bloody well works• We’ve been doing this all along• If you are working with an object of a given class

within the code of that class, you have direct access

• You get so used to this that when the question is posed directly, the answer may not occur to you

Page 35: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

35

• However, it is a question worth asking and the book’s extended answer is worth considering

• You get brainwashed into the idea that encapsulation is good and one “thing” should be protected from another

• If encapsulation is so good, why isn’t one object of a class protected from another object of the same class?

• Not to worry, the previous question is rhetorical

Page 36: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

36

• The point is to recognize that in the overall design of Java, access modifiers apply at the class level, not the object level

• It’s not clear that finer grained access control would gain you anything

• It is less clear how you might accomplish that goal without complicated new constructs and syntax

• It’s even less clear that you could successfully write/read/understand code that had such limited visibility built in

Page 37: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

37

• The book now starts arguing the other side of the question

• I have always maintained that instance variables should be private and methods should be public

• The explicit use of the protected access modifier came up in the discussion of the clone() method

• Notice that with respect to methods, protected is more limited than public

Page 38: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

38

• However, the book suggests that it may be possible to declare some instance variables protected rather than private

• This eases limitations on visibility• For example, it would give subclasses direct access to

their inherited instance variables• In some cases this might be worth doing• In a few instances the authors have done something

like this and it has made for simpler code (especially in subclasses)

Page 39: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

39

• This may increase the utility and ease of writing additional code

• It may also increase the mischief that other code writers can create

• Overall, it decreases the limitation of responsibility for your code

• In other words, using the authors’ terminology for this chapter, by giving other code writers more opportunity, you are increasing your responsibility

Page 40: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

40

• However, this is not responsibility in a wholly positive sense, responsibility for yourself

• It is a kind of negative responsibility, where you become responsible for the potential evil that other programmers might work on your code

• You have to consider this carefully before making a decision to do something like this

Page 41: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

41

Summary

• Note, first of all, that material follows the summary

• This plan is followed in all of the chapters which introduce a category of design patterns

Page 42: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

42

Summary• Simply stated, a developer is responsible for the inclusion

of suitable attributes and the implementation of suitable methods for classes

• Along with choosing the right attributes and functionality, the developer should make sure that the names of methods tell what they do, to the extent possible

• In certain circumstances you may increase your responsibility by choosing a less limiting access modifier for some of what you implement

• Whatever you do, you can’t escape responsibility

Page 43: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

43

Beyond Ordinary Responsibility

• Most of the foregoing discussion centered on this idea:

• The goal is to develop classes so that objects are independent and self-sufficient

• In other words, developer responsibility begins at the class design level

• This idea can be summarized as distributed responsibility

Page 44: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

44

• The design patterns of the following chapters will expand on this idea

• In other words, what patterns exist so that responsibility can be passed along when necessary?

• The following table lists different responsibility intents along with the names of the new design patterns which will implement them

Page 45: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

45

Page 46: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

46

• The intent of each design pattern is to solve a problem in a context

• Collectively, these are the situations that these design patterns address:

• Situations where the default goal of distributing responsibility as much as possible will not solve a responsibility problem

• It is necessary to centralize or pass responsibility in order to handle it successfully in a given context

Page 47: Design Patterns in Java Part II Responsibility Patterns Chapter 7 Introducing Responsibility

47

The End