cf.Objective() 2017 - Design patterns - Brad Wood
-
Upload
ortus-solutions-corp -
Category
Software
-
view
510 -
download
2
Transcript of cf.Objective() 2017 - Design patterns - Brad Wood
![Page 1: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/1.jpg)
Design PatternsCOMMON SOLUTIONS TO COMMON PROBLEMS
Brad Wood@bdw429s
Ortus Solutions
![Page 2: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/2.jpg)
Me
● Work for Ortus Solutions● Developer Advocate● Love rewriting Node code in CFML● Lead developer of CommandBox CLI● Live in Kansas City● Musician● 3 Ridiculously cute daughters● Like eating spicy foods
![Page 3: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/3.jpg)
Design Patterns
![Page 4: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/4.jpg)
Software Craftsmanship
![Page 5: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/5.jpg)
Design Patterns
Christopher Alexander, architect
Born in Vienna in the 30’s
![Page 6: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/6.jpg)
Architectural Design Patterns
![Page 7: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/7.jpg)
A Pattern Language
1977 book on architecture, urban design, and community livability
The book creates a new language, what the authors call a pattern language derived from timeless entities called patterns.
Patterns describe a problem and then offer a solution. (253 patterns)
![Page 8: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/8.jpg)
What is a Pattern?
“Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.”
Christopher Alexander
![Page 9: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/9.jpg)
A Pattern Language
37 HOUSE CLUSTER
76 HOUSE FOR A SMALL FAMILY
159 LIGHT ON TWO SIDES OF EVERY ROOM
![Page 10: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/10.jpg)
Gang of Four (GoF)
![Page 11: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/11.jpg)
Design Patterns:Elements of Reusable Object-Oriented Software
Inspired by Christopher’s work
23 programming patterns
Written by the “Gang of Four” in 1994
● Erich Gamma● Richard Helm● Ralph Johnson● John Vlissides
![Page 12: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/12.jpg)
Design Patterns:Elements of Reusable Object-Oriented Software
Creational Patterns
● Abstract Factory● Prototype● Singleton
![Page 13: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/13.jpg)
Design Patterns:Elements of Reusable Object-Oriented Software
Structural Patterns
● Composite● Decorator● Facade
![Page 14: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/14.jpg)
Design Patterns:Elements of Reusable Object-Oriented Software
Behavioural Patterns
● Chain of Responsibility● Iterator● Strategy
![Page 15: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/15.jpg)
Inspiration, not copy/paste examples
“The examples are there for inspiration and explanation of the ideas in the patterns. They aren't canned solutions; in all cases you'll need to do a fair bit of work to fit them into your application.”
Martin Fowler
![Page 16: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/16.jpg)
Let’s look at some examples
![Page 17: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/17.jpg)
Object Factory
https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)
![Page 18: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/18.jpg)
Object Factory
● An object that creates other objects● Abstracts details of how the final objects are created● Removes creation code from inside object to separate concerns● Often used with the dependency injection pattern● CFML Examples are WireBox or DI/1
![Page 19: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/19.jpg)
Singleton
https://sourcemaking.com/design_patterns/singleton
![Page 20: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/20.jpg)
Singleton
● Ensure class only has one instance● Provide global access to this instance● Just-in-time initialization● Often times doesn’t hold state● Object must be thread safe!
![Page 21: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/21.jpg)
Singleton
function onApplicationStart() {
application.myService = new models.myService();
}
![Page 22: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/22.jpg)
Strategy
https://sourcemaking.com/design_patterns/strategy
![Page 23: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/23.jpg)
Strategy
● Define a family of algorithms● Each one is encapsulated and interchangeable● Often times each strategy implements an interface● Each implementation can be different● Strategies can be chosen at runtime● Strategy in use is invisible to the program
![Page 24: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/24.jpg)
Strategy
logger.setAppender( new fileAppender() );
logger.logMessage( ‘This is my message’ );
logger.setAppender( new dbAppender() );
logger.logMessage( ‘This is my message’ );
![Page 25: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/25.jpg)
Decorator
https://sourcemaking.com/design_patterns/decorator
![Page 26: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/26.jpg)
Decorator
● Add responsibilities to a class dynamically● Alternative to subclassing (not really an “is-a”)● Decorator wraps original class● Wrapping can be recursive● Can be applied at runtime● User of class does not know (or care) if it’s been decorated
![Page 27: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/27.jpg)
iceCream = new iceCream();
iceCream.make();
sprinkledIceCream = new sprinklesDecorator( iceCream );
sprinkledIceCream.make();
Decorator
![Page 28: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/28.jpg)
Adapter
https://sourcemaking.com/design_patterns/adapter
![Page 29: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/29.jpg)
Adapter
● Modify the API of a class to be different● Can “adapt” a class to work in another system● Wraps the original class with a new interface● Allows greater reuse● Doesn’t modify original class
![Page 30: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/30.jpg)
Adapter
oldCache = new oldCacheEngine();
oldCache.retrieve( ‘item’ );
adaptedCache = new cacheAdapter( oldCache );
adaptedCache.get( ‘item’ );
![Page 31: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/31.jpg)
Front Controller
https://en.wikipedia.org/wiki/Front_controller
![Page 32: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/32.jpg)
Front Controller
● A single point of entry for a web app● Simplifies URL routing● Makes global concerns like security checks easier● Utilizes a controller to dispatch to the appropriate handler● Usually index.cfm in CFML apps
![Page 33: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/33.jpg)
Front Controller
yoursite.com/index.cfm?event=main.index
![Page 34: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/34.jpg)
Chain of Responsibility
https://sourcemaking.com/design_patterns/chain_of_responsibility
![Page 35: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/35.jpg)
Chain of Responsibility
● You have a large or dynamic list of handlers that need to respond to a request
● You don’t want to couple the sender to the responders● Creates a pipeline of linked handlers● Each handler calls the next link in the chain● A handler can abort the chain by not calling the next handler
![Page 36: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/36.jpg)
Chain of Responsibility
function securityHandler( request ) {
if( !request.params.authenticated ){
throw ‘Not logged in’!
}
// Pass control to the next link in the chain
request.proceed();
}
![Page 37: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/37.jpg)
Memento
https://sourcemaking.com/design_patterns/memento
![Page 38: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/38.jpg)
Memento
● Capture and externalize an object's internal state● Can be used to “snapshot” an object● Can be used to restore an object to a previous state● Great for serialization● Can include composed objects
![Page 39: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/39.jpg)
Memento
oUser = userService.loadUser( id=123 );
currentUserState = oUser.getMemento();
![Page 40: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/40.jpg)
Observer(publish/subscribe)
https://sourcemaking.com/design_patterns/observer
![Page 41: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/41.jpg)
Observer (publish/subscribe)
● Defines “events” that are broadcast ● Defines zero or more observers who are listening to those events● Promotes decoupling of a large system● Listener can receive data about the event that has happened● Bind listeners at runtime for dynamic behaviors● Don’t call us, we’ll call you!
![Page 42: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/42.jpg)
Observer (publish/subscribe)
$.ajax({
url: "test.html",
context: document.body
}).done(function() {
$( this ).addClass( "done" );
});
![Page 43: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/43.jpg)
Double Checked Locking
https://en.wikipedia.org/wiki/Double-checked_locking
![Page 44: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/44.jpg)
Double Checked Locking
● Protects creation of a shared resource with multithreading● Reduces overhead of acquiring exclusive locks by first performing
a read-only check● If creation is required, only then is an exclusive lock acquired● Once a thread has the exclusive lock, the check is performed a
second time to ensure another thread hasn’t completed it● Ensures thread safety without excessive locking
![Page 45: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/45.jpg)
Double Checked Locking
if( isDefined( 'data' ) ){ return data; }
lock name="generateData" type="exclusive" timeout=60 {
if( isDefined( 'data' ) ){ return data; }
data = produceData();
return data;
}
![Page 46: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/46.jpg)
Anti-patterns(Avoid these!)
![Page 47: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/47.jpg)
Anemic Domain Model
https://en.wikipedia.org/wiki/Anemic_domain_model
![Page 48: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/48.jpg)
Anemic Domain Model
● When domain model is too “thin” and lacks any behavior● Beans are only value objects with no behavior present● Services are empty, meaning business logic has probably ended
up in your controllers or views● Creates excessive classes● Bloats application code
![Page 49: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/49.jpg)
Anemic Domain Model
component accessors=true {
property name=’name’;
property name=’age’;
property name=’department’;
}
![Page 50: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/50.jpg)
God Object
https://sourcemaking.com/antipatterns/the-blob
![Page 51: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/51.jpg)
God Object
● A class with too much responsibility● API is watered down with many unrelated methods● Usually happens over time as code is added and never refactored● Hard to maintain and test● Lazy domain design and lack of planning
![Page 52: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/52.jpg)
God Object
util = new generalControllerUtil();
util.createOrder();
util.addUser();
util.login();
util.runScheduledTasks();
util.orderPizza();
![Page 53: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/53.jpg)
Premature Optimization
https://shreevatsa.wordpress.com/2008/05/16/premature-optimization-is-the-root-of-all-evil/
![Page 54: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/54.jpg)
Premature Optimization
● Coding early-on for perceived efficiency● Sacrificing good design, maintainability● Often times overstating a negligible speed improvement● Sometimes “proven” by a flawed “loop test”● The “root of all evil” -- Donald Knuth
![Page 55: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/55.jpg)
Improbability Factor
https://en.wikipedia.org/wiki/Improbability_factor
![Page 56: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/56.jpg)
Improbability Factor
● Leaving known bugs in your system because they’re “not likely to happen”
● Gambling with fate to save time and be lazy● This is just inviting Murphy’s Law to come into full effect● Can bite you later at the worst possible time
![Page 57: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/57.jpg)
Improbability Factor
reportService.runAsyncReport();
// Meh, this should be enough
sleep( 5000 );
fileRead( ‘/reports/sales.pdf’ );
![Page 58: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/58.jpg)
Honorable Mentions
![Page 59: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/59.jpg)
Law of Demeter
https://en.wikipedia.org/wiki/Law_of_Demeter
![Page 60: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/60.jpg)
Law of Demeter
● Principle of least knowledge● A unit of software should have limited knowledge about the other
units● Software units should talk to friends and not to strangers● Keeps low coupling between systems● Rule of thumb: be careful accessing methods on objects obtained
from other objects (the “dot” rule)
![Page 61: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/61.jpg)
Law of Demeter
orderCity = cart
.getOrder()
.getOrderDetails()
.getUser()
.getAddress()
.getCity()
.getName();
![Page 62: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/62.jpg)
Principle of Least Astonishment
https://en.wikipedia.org/wiki/Principle_of_least_astonishment
![Page 63: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/63.jpg)
Principle of Least Astonishment (POLA)
● Applies to UI and software design● "If a necessary feature has a high astonishment factor, it may be
necessary to redesign the feature”● User controls should have a consistent behavior● Predictable software is easier to use● Basically, don’t make your users go “WTF!?”
![Page 64: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/64.jpg)
Principle of Least Astonishment (POLA)
// Has side effect of removing all login history
user.getAPIKey();
![Page 65: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/65.jpg)
Brook’s Law
https://en.wikipedia.org/wiki/Brooks%27s_law
![Page 66: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/66.jpg)
Brook’s Law
● “Adding manpower to a late software project makes it later"● Coined by Fred Brooks in his 1975 book The Mythical Man-Month● Software development is knowledge work, and not fungible ● Throwing devs at a project will slow it down at first● A larger team has more points of contact● If 1 woman can have a baby in 9 months, it doesn’t mean 9
women can have a baby in 1 month
![Page 67: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/67.jpg)
Resources
![Page 68: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/68.jpg)
Head First Design Patterns: A Brain-Friendly Guide
![Page 69: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/69.jpg)
Software Architecture Design Patterns in Java
![Page 70: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/70.jpg)
https://sourcemaking.com/design_patterns
![Page 71: cf.Objective() 2017 - Design patterns - Brad Wood](https://reader033.fdocuments.us/reader033/viewer/2022051521/5a66d3d77f8b9a3c0e8b57eb/html5/thumbnails/71.jpg)
Thanks for coming!
Contact me
● [email protected]● www.codersrevolution.com● @bdw429s● Ortus Solutions