[ Pobierz całość w formacie PDF ]
.From the Library of Santiago Itzcoatl Salinas Reyna231Chapter 6: Intermediate Pattern CompositionsFulfill Method Object StructuralIntentTo provide an implementation for a previously abstracted method, therebyfulfilling the contract made by Abstract Interface that a later subclass wouldprovide such an implementation.MotivationAbstract Interface promises that some subclass will provide a propermethod implementation to a method interface declared in a class intendedto be a superclass.Inheritance lets us define that subclass, and FulfillMethod describes how to go about fulfilling that prior promise by com-bining the two pattern instances.This approach lets us cleanly separate the abstraction of the methodin the superclass from any number of possible subclasses that may (or maynot) provide an implementation for it.ApplicabilityUse Fulfill Method when:" Implementation of a method has been deferred using AbstractInterface." A subclass of the class specified in Abstract Interface is able to handlethe functionality of the method as promised.ParticipantsAbstractorThe class type that declares an interface foroperation.FulfillerThe class type that defines a method body foroperation; inheritsfromAbstractor.operationThe method that was declared in Abstractor and defined inFulfiller.From the Library of Santiago Itzcoatl Salinas Reyna232Chapter 6: Intermediate Pattern CompositionsStructureAbstractorFulfill MethodAbstractorSuperclassAbstractInheritanceAbstractClassInterfaceoperation Subclassoperation()BackgroundConcreteClassoperation()operation FulfillerPINbox-only version (also used in Figure 4.4):AbstractorFulfill MethodAbstractorSuperclassAbstractBackgroundInheritanceInterfaceoperation Subclassoperation FulfillerCollaborationsAbstractordefines an interface for a method, andFulfillerpro-vides the implementation.Fulfillersubclasses fromAbstractortogain the appropriate typing and interface.Abstractoris the primary class in the instance of Abstract Interface,andAbstractorandFulfillerare related through an instance ofInheritance.From the Library of Santiago Itzcoatl Salinas Reyna233Chapter 6: Intermediate Pattern CompositionsConsequencesFulfillerrelies onAbstractorfor the interface to the implementedmethod.These two must be kept in sync, and there are times when a shuf-fling interface at the top of a class hierarchy can have far-reaching effectson its subclasses.In cases where this is expected, a solution utilizing Del-egation may be preferred.A solution using Delegation allows the externalinterface to be independent of the implementation object.Alternatively, ifonly one class/object is mandated, Conglomeration can be used to handoff the task to private methods internal to the type, thereby preserving theinterface/implementation encapsulation.ImplementationEvery language that supports inheritance and abstract methods, regardlessof expression, supports Fulfill Method.Following are some examples basedon the examples from Abstract Interface.In C++:1 class Abstractor {public:3 virtual void operation() = 0;};5class Fulfiller :7 public Abstractor {public:9 void operation() {// Perform the appropriate work11 };};In Java, the method is included in an interface or is in an abstract class:public interface Abstractor {2 public void operation();};4public abstract class AnotherAbstractor {6 public abstract void operation2();public void operation3();8 };10 public class Fulfillerextends AnotherAbstractor12 implements Abstractor {public void operation() {14 // Perform the appropriate work}16 public void operation2() {From the Library of Santiago Itzcoatl Salinas Reyna234Chapter 6: Intermediate Pattern Compositions// Perform the appropriate work18 }};In Python 3.x:1 class Abstractor(metaclass=ABCMeta):@abstractmethod3 def operation(self,.):// Default implementation allowed5 return7 class Fulfiller(Abstractor):def operation(self,.):9 // Perform the appropriate workpassRelated PatternsFulfill Method is composed of two of the core EDPs: Abstract Interface andInheritance.Because Fulfill Method fulfills the promise made by AbstractInterface, it is found in almost every case where Abstract Interface is.Inthose cases where Fulfill Method doesn t accompany Abstract Interface, theresulting abstract class isn t usable in code until a subclass completes thepromise.Multiple Fulfill Method instances can be found later in this chap-ter under Objectifier.Fulfill Method can also be found as a necessary com-ponent of most of the Gang of Four patterns, including Proxy, Command,Iterator, Observer, State, Decorator, Prototype, Template Method, and manyothers [21].From the Library of Santiago Itzcoatl Salinas Reyna235Chapter 6: Intermediate Pattern CompositionsRetrieve New Object ManagementIntentUsed when a new instance is needed and the creation of that instance is acomplex or expensive procedure that needs to be encapsulated in anotherobject.The returned object is guaranteed not to have any other referencesto it.MotivationOften, a newly created object needs to be a pristine object with well-definedownership.Creating such an object locally is always an option, but it can bea suboptimal decision if, for instance, the object to be created is determinedby a rather complex behavior.An example would be deciding which objectto create on the basis of which reply is given in response to a databasequery.Any object creation process that is wrapped in complex logic ortransactions that may take significant time isn t code that lends itself to copyand paste reuse.We want to both centralize such logic and encapsulate itinto its own method.This encapsulation of logic leads to other issues, of course.If thecreated object can be referenced by a number of sources and the mem-ory model is an unmanaged one such as in C++, then any piece of codewith such a reference to the object can request its destruction, leavingthe remainder of the references pointing to an invalid object.Alterna-tively, none of the referring objects may request its destruction, leadingto a memory leak because the object becomes unreachable while still resi-dent.Garbage collection can help with this issue, but well-defined memorymanagement starts with small decisions.One such decision is to make sure that only the recipient of a Retrievehas access to the object being retrieved, thereby establishing a clear andprecise ownership.This can be done almost transparently by returninga copy of an object, because the copy will create a fresh instance [ Pobierz całość w formacie PDF ]