4. Introduction
• Templates for solving common problems
• Problem and solution description
• Not a library, not an algorithm!
• Customized Solution
• Reusability and Extensibility
• Patterns for different purposes
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
5. Basic Principles
• Program to an interface, not an
implementation
• Composition over Inheritance
• iOS = Look & Feel driven design
• Design first than develop
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
6. MVC
• Model View Controller
• Most Cocoa Touch frameworks
• Separation and Communication
• Compound pattern
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
26. Outlets, Targets, Action
• Connect User Interface objects to
application specific operations
• Connect views and controllers
• based on Objective-C’s selector pattern
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
27. Outlets, Targets, Action
• Outlet is a reference to another object
• id or IBOutlet
• Stored in instance of
NSNibOutletConnector
• -set<Outlet>:
• When awakeFromNib is called all outlets
are connected
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
28. Outlets, Targets, Action
• Target is a special type of outlet
• Stored in instance of
NSNibControlConnector
• Actions can be any method that returns
void and accepts one argument
• Stored as selectors
• UIApplication sendAction:to:from
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
29. Singleton
• UIAccelerometer
• Shared resources
• Only one instance
• Global point access
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
32. Singleton
+(Singleton *)sharedInstance
{
@synchronized(self)
{
if (sharedSingleton_ == nil)
{
sharedSingleton_ = [[Singleton allocWi] init];
}
}
return sharedSingleton_;
}
+(Singleton *)sharedInstance
{
static dispatch_once_t pred = 0;
__strong static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = [[self alloc] init]; // or some other init method
});
return _sharedObject;
}
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
33. Category
• Addition of methods to an object without
subclassing
• Replace methods at runtime
• No instance variables!
• Spread implementation over various files
• Different methods in different frameworks
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
35. Informal Protocol
• Category header only to define classes that
might or might not be implemented
- (void)awakeFromNib
{
if ([UIControl instancesRespondToSelector:@selector(awakeFromNib)]) {
[super awakeFromNib];
}
}
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
36. Anonymous Category
• No category name, empty parentheses
• Must be implemented in original class
• used for organizing private methods
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
37. Factory Method
• Interface for creation
• Creator vs. Product
• Defer instantiation to subclasses
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
41. Façade
• Unified, higher level interface to a set of
different interfaces
• Gateway to a set of subclasses
• Hide complexity
• Layer subsystems
• NSPersistantStoreCoordinator
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
43. Mediator
• Encapsulates objects interaction
• Objects only know the mediator
• Hub of communication
• Many-to-Many to One-to-Many
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
44. Mediator
anAirplane anAirplane
control tower
anAirplane anAirplane
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
45. Template Method
• Skeleton of an algorithm that partly needs
to be implemented by subclassing
• Used if specific behaviour can vary and
common behaviour is needed
• Used for so called “Hooks”
• Assure primitive method implementation
• “drawRect”, “dealloc”
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
46. Template Methods
Abstract Class ...
[self primitiveOperation1]
templateMethod ...
primitiveOperation1 [self primitiveOperation2]
...
primitiveOperation2
Concrete Class
primitiveOperation1
primitiveOperation2
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
47. References
• Pro Objective-C Design Patterns for iOS
• Cocoa Design Patterns
• Design Patterns: Elements of Reusable
Object-Oriented Software
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
50. Composite
• Hierachies
• Solve structural problem
• Tree with different node objects but same
base type
• UIViews are organized as composite
structure
• New operations:Visitor Pattern
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
52. Visitor
• Extending a classes functionality by using an
external class
• Usually used in combination with the
Composite Pattern
• Protocol defines visitXXX method
• Elements have acceptVisitor method
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
53. Proxy
• Placeholder for different, bigger object
• Lazy image loading
• Mail Attachment
• Remote Proxy
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
54. Decorator
• Attach additional responsibilities to an
object dynamically
• TextView with Scroll
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
55. Anonymous Type
• Type <id>
• Pointer to an Objective-C object
• No specific information
• Can receive messages!
• Heterogeneous Containers
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
56. Accessors
• Funnel access to an object’s properties
• Adhere to memory management
• Necessary for key-value coding
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
57. Archiving
• Serialization
• Encode an objects state into an archive
• Used with Interface Builder
• Used to create “deep copies”
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
58. Memento
• Save current state of an object
• Hide loading and saving of an object
• Originator, Memento and Caretaker
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
59. Proxy
• Placeholder for different objects
• Save memory
• Local representative for remote object
• Access control
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
60. Flyweight
• Share objects and keep them in a pool
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
61. Archiving
• Serialization
• Save an objects state into an archive
• Interface Builder
• Deep Copy
iOS Design Patterns 19/11/2011 - Barcelona Developer Conference @ismaeldm @aquarioverde
Notes de l'éditeur
\n
\n
\n
There&#x2019;s about 30 known patterns, probably more\n12 design patterns we consider most important\n&#x201C;The Gang of Four&#x201D; - Design Patterns\n\nPurposes: (Creational, Structural, Behavioural)\nObject Creation\nInterface Adaption\nDecoupling Objects\nAbstract Collection\nBehavioural Extension\nAlgorithm Encapsulation\nPerformance and Object Access\n
interface (protocol): \nclients don&#x2019;t have to be aware of the type of object they are using\nabstract classes are more flexible\nprotocols permit kind of multiple-inheritance\n\ninheritance:\nsubclass knows details of super-class (no encapsulation)\ncan not change the inherited implementation at runtime\nchange in super-class need change in subclass\ncan&#x2019;t reuse subclasses\n\ncomposition:\nwell defined interfaces\ndefined dynamically at runtime\nno details visible\nfew implemenation dependencies\neasy object replacement\nfocus on one task\nsmall hierarchies\n\n\n
has been around in other programming languages for a long time\nseparates the three basic parts of an application and defines the way they communicate\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
1.- Basic idea : 2 objects coordinates to solve a problem. One is more general and intended for reuse, keep a reference to the other (the delegate) and sends messages to it.\n\n2.- Messages indicate that something happened and:\n- give the delegate an opportunity to make extra process (reacts to changes)\n- ask the delegate for critical information that will control what happens (influence the behaviour)\n\n3.- Es una alternativa al subclassing muy utilizada en Cocoa\nReduce the need to subclass objects to implement application-specific behaviour\n\n4.- Reduce the coupling. Coupling is so loose that the object can function without any delegate and a delegate is free to implement any subset of methods.\n\n5.- Convenciones de nombres en los mensajes: \n- should : send before change, expected to return a value. Ex: BOOL\n- will : send before change, informative, not expected to return a value\n- did : send after change\n\n\nEjemplo : en MVC no es conveniente poner detalles relacionados con la aplicaci&#xF3;n en la vista. Es decir, que la l&#xF3;gica que controla el comportamiento de la vista va en el Controller y la vista se encarga de avisar al controller de que ha ocurrido un evento al que necesita responder de alguna manera y el controller le va a decir c&#xF3;mo. \nEn MVC el controller es un Delegate (Strategy?) para la View. La View sabe c&#xF3;mo dibujar pero no sabe el qu&#xE9; hasta que el controller se lo dice.\n\n
\n
one to many relationship\n
one to many relationship\n
when to use them:\n2 types of abstraction that depend on each other\nchanges on a set of objects that can vary\nnotifying objects without knowing them\n\n\n
object: any other object that will be invoked when notified\n
1.- Command &#x201C;encapsulates a request (call to a method) as an object&#x201D;\nSeparates an object sending a message from the object that receive and evaluate the message.\nThe originator of the message (Client) encapsulates a request by binding together one or more actions on a specific receiver.\n\n2.- En Cocoa est&#xE1; implementado mediante la clase NSInvocation que contiene toda la informaci&#xF3;n necesaria para llevar a cabo una acci&#xF3;n (target, selector, arguments, return value) y que pueden ser modificados en cualquier momento.\n\n3.- El selector identifica de forma un&#xED;voca un mensaje enviado a un objeto receptor. \nEn cierta manera el Target-Action mechanism (que veremos a continuaci&#xF3;n) hace uso de este patr&#xF3;n dado que las objetos Control (p.ej.:UIButton) encapsulan el target y la acci&#xF3;n y se env&#xED;an cuando el usuario activa dicho control. La action est&#xE1; determinada por un selector que no es m&#xE1;s que un identificador de un m&#xE9;todo/mensaje. En UIKit un control (UIButton) mapea un target y una action a uno o m&#xE1;s eventos multitouch que ocurran sobre el control.\n\n4.- Usos : undo/redo stacks, rollback transactions, progress bars (sequences of commands executed in order), Wizards with finish action,\n\nActores principales : client, invoker, receiver\nClient : instantiates the command object and provides information required to call the method at a later time.\nInvoker : decides when the method should be called.\nReceiver : instance of the class that contains the method&#x2019;s code\n\nUsed to construct components that need to delegate, sequence or execute method calls at a time of their choosing without the need to know the owner of the method or the method parameter.\n\n\n
vs subclassing or unique id\ndoes not break MVC\n
\n
The ability of the target to point to any object and the fact that the action is variable provide high flexibility.\n\n[someControl setAction:@selector(@&#x201D;copy&#x201D;)];\nNSSelectorFromString()\nNSStringFromSelector()\n\n[NSApplication sharedApplication] sendAction:[self action] to:[self target] from:self];\n\n
1.- Ejemplo de uso : acceso al aceler&#xF3;metro. Se trata de un recurso al que no tiene sentido instanciar m&#xE1;s de una vez en nuestra aplicaci&#xF3;n. Al fin y al cabo el servicio que nos ofrece es &#xFA;nico.\n2.- Su uso se da cuando, por ejemplo, queremos dar un &#xFA;nico punto de acceso a un recurso.\n3.- C&#xF3;mo podemos modelar este comportamiento cuyas caracter&#xED;sticas podr&#xED;amos resumir en: \n- la creaci&#xF3;n de una clase de la que tan solo exista una &#xFA;nica instancia durante toda la vida de nuestra aplicaci&#xF3;n\n4.- - y tener un punto de acceso global a dicha instancia (Factory Pattern)\n\n\n\n\n\nPor ejemplo el aceler&#xF3;metro con la clase UIAccelerometer y el acceso via sharedAccelerometer\n\n\n\n\n\n\nThink about resources that can be shared only in a system and no copies of them can be made available to others.\nA singleton class in an object-oriented application always returns the same instance of itself. It provides a global access point for the resources provided by the object of the class. A design pattern that is related to these kinds of designs is called the Singleton pattern.\nEnsures a class has only one instance, and provide a global point of access to it\nThe Singleton pattern provides a well-known access point to client classes that want to create a unique instance of and access to a shared resource.\nWhen?\nThere must be exactly one instance of a class with which it must be accessible from a well-known access point, e.g., a factory method \nThe sole instance can be extended only by subclassing, and it won&#x2019;t break client code with the extended object \n\n\nObjective-C implementation\n1.- simple implementation\n2.- avoid alloc/init -> allocWithZone, retain, release, autorelease, retainCount\nalloc calls allocWithZone\n3.- subclassing -> [NSAllocateObject ([self class],0,NULL) init]\n4.- thread safety\n- via synchronize\n- via initialize trick (runtime call first time a message is sent to a class)\n\n
Objective-C implementation\n1.- simple implementation\n- acceso global a la &#xFA;nica instancia (factory method)\n- static instance\nCon esta primera implementaci&#xF3;n tan solo estoy asegurando que todas las veces que llame al m&#xE9;todo de clase sharedSingleton me va a devolver la misma instancia.\n\nEn el caso de herencia tan solo deber&#xED;a sustituir la creaci&#xF3;n por la llamada:\n\nsharedSingleton_ = [NSAllocateObject([self class], 0, NULL) init];\n
2.- avoid alloc/init -> allocWithZone, retain, release, autorelease, retainCount\nalloc calls allocWithZone\nC&#xF3;mo evitar que se puedan crear nuevas instancias via alloc/init? Sobreescribiendo algunos m&#xE9;todos.\n- allocWithZone es llamado por alloc\n- allocWithZone hace retain para simular el mismo comportamiento y que el cliente, cuando haga release de su variable no de problemas\n- ponemos el contador de retain al m&#xE1;ximo porque una vez inicializado el objeto permanece con vida hasta que la aplicaci&#xF3;n termina\n- en el m&#xE9;todo sharedInstance deberemos llamar a [super allocWithInit:] dado que hemos sobreescrito el propio\n
3.- thread safety\n- via synchronize\n- via GCD (Grand Central Dispatch) & ARC (Automatic Reference Counting)\n- otros ... p.ej.: via initialize trick (runtime call first time a message is sent to a class)\nHacer referencia a la sesi&#xF3;n de Ricardo a continuaci&#xF3;n sobre el ARC\n
simplify development for multiple developers\ngroup commonly used methods\nfix bugs in existing classes\n\nCategory or subclass?\n\nExamples in Cocoa:\nNSObject has 69 Categories!\n
use prefixes in category naming!\nother example: extending NSArray functionality\n\n
fool the compiler\n
\n
1.- Factory methods encapsulate the creation of objects. This can be useful if the creation process is very complex, for example if it depends on settings in configuration files or on user input\nEs uno de los patrones de creaci&#xF3;n e intenta resolver el problema de la creaci&#xF3;n de objetos sin tener que especificar la clase concreta a la que pertenecen.\n\n\n2.- Modelamos con este patr&#xF3;n dos tipos de clases, las creadoras y las relacionadas con los productos que se crean.\n3.- El cliente que utiliza el patr&#xF3;n conoce que tiene una f&#xE1;brica que le va a devolver un objeto producto cuya clase padre es la que conoce y le interesa pero que internamente va a ser una instancia de una subclase de producto dado que dependiendo de las circustancias la f&#xE1;brica crear&#xE1; un producto u otro.\nEn el creador tendremos el metodo de creaci&#xF3;n (Factory Method) que devuelve la clase producto que corresponda y que adem&#xE1;s sea subclase de la clase abstracta producto.\nSe usa cuando:\n- una clase no puede anticipar a qu&#xE9; clase pertenecen los objetos que debe crear\n- una clase quiere que sus subclases sean las que especifiquen a qu&#xE9; clase pertenecen los objetos que crea\n\n\nEjemplo de alquiler de coches. Quiero un coche pero me da igual si es de clase A, B, o C. Eso lo decidir&#xE1; el creator dependiendo de la disponibilidad\n\n\n\nEjemplo: clase ImageReader con un m&#xE9;todo que devuelve un objeto de tipo DecodedImage. La clase ImageReader es el Producto. La clase ImageFactory es la interface del Creador con un m&#xE9;todo getImageReader. Las subclases de ImageFactory implementan dicho m&#xE9;todo.\n\nFactory\n\npublic class ImageReaderFactory\n{\n public static ImageReader getImageReader(InputStream is)\n {\n int imageType = determineImageType(is);\n \n switch(imageType)\n {\n case ImageReaderFactory.GIF:\n return new GifReader(is);\n case ImageReaderFactory.JPEG:\n return new JpegReader(is);\n // etc.\n }\n }\n}\n\nProduct\n\npublic interface ImageReader\n{\n public DecodedImage getDecodedImage();\n}\n \npublic class GifReader implements ImageReader\n{\n public DecodedImage getDecodedImage()\n {\n // ...\n return decodedImage;\n }\n}\n \npublic class JpegReader implements ImageReader\n{\n public DecodedImage getDecodedImage()\n {\n // ...\n return decodedImage;\n }\n}\n\nOtro ejemplo : testing de una clase A que tiene un metodo M que devuelve una instancia de otra clase B. Para testear la clase A sin tener en cuenta la clase B, lo que se hace es crear una subclase de A (TestA) en la que se sobreescribe el m&#xE9;todo M para que devuelva una clase FakeB subclase de B. \n\n\n
La elecci&#xF3;n de qu&#xE9; Creator utilizar se puede dar en:\n- la clase Creator. Dependiendo de las condiciones se eligir&#xE1; una u otra subclase para devolver el Producto. No existen entonces ConcreteCreator&#x2019;s sino que un &#xFA;nico creator devuelve objetos ConcreteProducts\n- el cliente directamente. La clase cliente, dependiendo de las condiciones crear&#xE1; una instancia de una u otra subclase de Creator para que devuelva el Producto (sin tener qu&#xE9; conocer c&#xF3;mo est&#xE1; implementado, es decir, a qu&#xE9; subclase de Producto pertenece). Ejemplo NSNumber\n
1.- Similar al patr&#xF3;n Factory Method.\n\n2.- A method to build collections of Factories\nProvides an interface for creating families of related or dependent objects without specifying their concrete classes\n\n3.- Idem que en el anterior\n\n\n\n\n\n\nEn este caso la interfaz de la clase creadora define m&#xE9;todos para crear diferentes clases de objetos que est&#xE1;n relacionados o que son dependientes entre ellos\nEncapsula un conjunto de Factories \n
Pasa lo mismo que con el anterior.\nEl cliente sabe qu&#xE9; ConcreteFactory debe utilizar dependiendo de las condiciones de entorno. A partir de ah&#xED; puede llamar a los diferentes m&#xE9;todos sabiendo que los objetos que devuelvan corresponden con las clases abstractas sin tener que preocuparse de la clase concreta.\nEjemplo : look&feel de la UI\n
similarity to Manager pattern\nlegacy application\n
example: Bank System (Account, Customer, Transaction)\n\n
\n\nMetafora de los pilotos de avi&#xF3;n que quieren aterrizar y en vez de hablar todos con todos se comunican con la torre de control\n\nDefine an object that encapsulates how a set of objects interact\nEl dise&#xF1;o OO promueve la separaci&#xF3;n del comportamiento en diferentes objetos. Esto conlleva que al final todos los objetos esten relacionados entre si y todos conozcan todo de todos. Esto reduce la reusabilidad.\nSin el Mediator, dado que la comunicaci&#xF3;n de cada objeto con el resto est&#xE1; definida en su misma clase, es dif&#xED;cil su reutilizaci&#xF3;n. En cambio si extraemos dicha comunicaci&#xF3;n a un objeto &#x201C;Director&#x201D; nos queda tan solo el comportamiento propio de la clase\nVentajas : \nsi queremos modificar el comportamiento tan solo debemos subclass el mediator y no el resto de objetos\ndecoupling de objetos\nreplaces many-to-many to one-to-many interactions\nsepara la definici&#xF3;n del comportamiento individual de cada objeto de la interacci&#xF3;n entre objetos\nImplementaci&#xF3;n:\nObjects communicates when events occurs\nMediator as an Observer\n
NOTA : Deber&#xED;a estar despu&#xE9;s del patr&#xF3;n Observer y de Notifications\n\nMetafora de los pilotos de avi&#xF3;n que quieren aterrizar y en vez de hablar todos con todos se comunican con la torre de control\nDefine an object that encapsulates how a set of objects interact\nEl dise&#xF1;o OO promueve la separaci&#xF3;n del comportamiento en diferentes objetos. Esto conlleva que al final todos los objetos esten relacionados entre si y todos conozcan todo de todos. Esto reduce la reusabilidad.\nSin el Mediator, dado que la comunicaci&#xF3;n de cada objeto con el resto est&#xE1; definida en su misma clase, es dif&#xED;cil su reutilizaci&#xF3;n. En cambio si extraemos dicha comunicaci&#xF3;n a un objeto &#x201C;Director&#x201D; nos queda tan solo el comportamiento propio de la clase\nVentajas : \nsi queremos modificar el comportamiento tan solo debemos subclass el mediator y no el resto de objetos\ndecoupling de objetos\nreplaces many-to-many to one-to-many interactions\nsepara la definici&#xF3;n del comportamiento individual de cada objeto de la interacci&#xF3;n entre objetos\nImplementaci&#xF3;n:\nObjects communicates when events occurs\nMediator as an Observer\n