November 30, 2010 Design Patterns No comments
November 30, 2010 Design Patterns No comments
Many people like watching box fights. But besides of this, someone have to pay for all of this, and most of the money come from people who put some money on boxers and then lose it. Or… maybe I’m wrong, but for this example, let it be so. Imagine that we have box fight tonight and there are two persons interested in game, so they OBSERVE fight and UPDATE their rates. One of them likes risks, so he always put money on boxer who has less chance to win, and other is very conservative and likes small bird in hand instead of big in the sky.
Observer is design pattern, that allows automatically update many observers if there was change in state of some subject object.
So, each gambler (Player, Observer) likes to adjust his rates, that is why he has Update() method.
public interface IObserver
{
void Update(ISubject subject);
}
public class RiskyPlayer : IObserver
{
public string BoxerToPutMoneyOn { get; set; }
public void Update(ISubject subject)
{
var boxFight = (BoxFight)subject;
BoxerToPutMoneyOn = (boxFight.BoxerAScore > boxFight.BoxerBScore) ? "I put on boxer B, if he win I get more!" : "I put on boxer A, if he win I get more!";
Console.WriteLine("RISKYPLAYER:{0}", BoxerToPutMoneyOn);
}
}
public class ConservativePlayer : IObserver
{
public string BoxerToPutMoneyOn { get; set; }
public void Update(ISubject subject)
{
var boxFight = (BoxFight)subject;
BoxerToPutMoneyOn = (boxFight.BoxerAScore < boxFight.BoxerBScore) ? "I put on boxer B, better be safe!" : "I put on boxer A, better be safe!";
Console.WriteLine("CONSERVATIVEPLAYER:{0}", BoxerToPutMoneyOn);
}
}
Here below we have subject which is observed by players:
public interface ISubject
{
void AttachObserver(IObserver observer);
void DetachObserver(IObserver observer);
void Notify();
}
public class BoxFight : ISubject
{
public List<IObserver> Observers { get; private set; }
public int RoundNumber { get; private set; }
private Random Random = new Random();
public int BoxerAScore { get; set; }
public int BoxerBScore { get; set; }
public BoxFight()
{
Observers = new List<IObserver>();
}
public void AttachObserver(IObserver observer)
{
Observers.Add(observer);
}
public void DetachObserver(IObserver observer)
{
Observers.Remove(observer);
}
public void NextRound()
{
RoundNumber++;
BoxerAScore += Random.Next(0, 5);
BoxerBScore += Random.Next(0, 5);
Notify();
}
public void Notify()
{
foreach (var observer in Observers)
{
observer.Update(this);
}
}
}
Usage, or how we build one-to-many relationship by attaching observer-s:
var boxFight = new BoxFight();
var riskyPlayer = new RiskyPlayer();
var conservativePlayer = new ConservativePlayer();
boxFight.AttachObserver(riskyPlayer);
boxFight.AttachObserver(conservativePlayer);
boxFight.NextRound();
boxFight.NextRound();
boxFight.NextRound();
boxFight.NextRound();
Output:
RISKYPLAYER:I put on boxer A, if he win I get more! CONSERVATIVEPLAYER:I put on boxer B, better be safe! RISKYPLAYER:I put on boxer B, if he win I get more! CONSERVATIVEPLAYER:I put on boxer A, better be safe! RISKYPLAYER:I put on boxer B, if he win I get more! CONSERVATIVEPLAYER:I put on boxer A, better be safe! RISKYPLAYER:I put on boxer B, if he win I get more! CONSERVATIVEPLAYER:I put on boxer A, better be safe!
Been very short explanation. Just take closer look on interfaces in examples, this should be enough to understand everything.
November 23, 2010 Design Patterns No comments
Did you ever think why so many things around us have tree-similar structure? Top management of your company can delegate some work to middle management, and it can delegate it to your direct manager, who will ask you and your colleagues do something. In one of your tasks you had to gather data for some customer into xml. XML has also tree-similar structure. Why? Because it is the best way to serialize data, that can have data, that can… You got that! Now imagine that you want to gather data for some document part by part.
Composite is design pattern that provides us tree-similar structural representing of classes, this allows us work uniformly with parents and Childs.
So interface that defines common requirements for parents and kids:
public interface IDocumentComponent { string GatherData(); void AddComponent(IDocumentComponent documentComponent); }
And here we see some leaf component implementation. It is Customer Component, which gathers some data about customer basing on id provided to the class.
public class CustomerDocumentComponent : IDocumentComponent { private int CustomerIdToGatherData { get; set; } public CustomerDocumentComponent(int customerIdToGatherData) { CustomerIdToGatherData = customerIdToGatherData; } public string GatherData() { string customerData; switch (CustomerIdToGatherData) { case 41: customerData = "Andriy Buday"; break; default: customerData = "Someone else"; break; } return string.Format("<Customer>{0}</Customer>", customerData); } public void AddComponent(IDocumentComponent documentComponent) { Console.WriteLine("Cannot add to leaf..."); } }
And not-leaf implementation of the component below. Please take into account that it simply loops through Childs and executes GatherData method.
public class DocumentComponent : IDocumentComponent { public string Name { get; private set; } public List<IDocumentComponent> DocumentComponents { get; private set; } public DocumentComponent(string name) { Name = name; DocumentComponents = new List<IDocumentComponent>(); } public string GatherData() { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine(string.Format("<{0}>", Name)); foreach (var documentComponent in DocumentComponents) { documentComponent.GatherData(); stringBuilder.AppendLine(documentComponent.GatherData()); } stringBuilder.AppendLine(string.Format("</{0}>", Name)); return stringBuilder.ToString(); } public void AddComponent(IDocumentComponent documentComponent) { DocumentComponents.Add(documentComponent); } }
Gluing parts to be some kind of document:
var document = new DocumentComponent("ComposableDocument"); var headerDocumentSection = new HeaderDocumentComponent(); var body = new DocumentComponent("Body"); document.AddComponent(headerDocumentSection); document.AddComponent(body); var customerDocumentSection = new CustomerDocumentComponent(41); var orders = new DocumentComponent("Orders"); var order0 = new OrderDocumentComponent(0); var order1 = new OrderDocumentComponent(1); orders.AddComponent(order0); orders.AddComponent(order1); body.AddComponent(customerDocumentSection); body.AddComponent(orders); string gatheredData = document.GatherData(); Console.WriteLine(gatheredData);
Output is somewhat similar to XML. At least I tried to keep it similar.
<ComposableDocument>
<Header><MessageTime>8:47:23</MessageTime></Header><Body>
<Customer>Andriy Buday</Customer>
<Orders>
<Order>Kindle;Book1;Book2</Order>
<Order>Phone;Cable;Headset</Order>
</Orders>
</Body>
</ComposableDocument>
Also GoF guys suggest having Remove(Component) and GetChild(int) methods in your Component, so you might want to add them. Just don’t limit yourself with any kind of explanations. You might have some unique need.
November 15, 2010 Design Patterns 4 comments
You have a boss, who doesn’t care who will be doing some work or how it will be done, he just want it to be started and completed at some point of time, say after customer signed contract. Since you are at high position you were asked to form team A that will be working at some project X, you also got list of high-level requirements from your boss. You should be ready to start all work at the moment your customer signs contract.
So you are Command – you encapsulate receiver team A and parameters to start work (project and requirements). Team and requirements are given to you by your boss – Client.
You are able to delegate all work to team A and provide requirements at the moment customer triggers process. Your customer is Invoker, they have contact to you, so can use you as they want.
Command – is design pattern that allows us encapsulate request, tune it with parameters as needed and then execute at one point of time, without knowing how actually executes work.
Client code
Here is how story looks from code perspective. Taking a look at client code (boss):
var customer = new Customer();
// for some reason boss always knows that company has money
// only for team Z
var team = new Team("Z");
// he also managed to get high-level list of requirements for you
var requirements = new List<Requirement>() { new Requirement("Cool web site"), new Requirement("Ability to book beer on site") };
// you should be ready to be invoked by Customer
ICommand commandX = new YouAsProjectManagerCommand(team, requirements);
customer.AddCommand(commandX);
// there is also here developer who can code at light speed
var heroDeveloper = new HeroDeveloper();
// boss decided to give him project A
ICommand commandA = new HeroDeveloperCommand(heroDeveloper, "A");
customer.AddCommand(commandA);
// when customer signs contract with boss
// your team and hero developer start executing their job
customer.SignContractWithBoss();
Command
Now lets take a look on two concrete commands:
public interface ICommand
{
void Execute();
}
public class YouAsProjectManagerCommand : ICommand
{
public YouAsProjectManagerCommand(Team team, List<Requirement> requirements)
{
Team = team;
Requirements = requirements;
}
public void Execute()
{
// implementation delegates work to concrete receiver
Team.CompleteProject(Requirements);
}
protected Team Team { get; set; }
protected List<Requirement> Requirements { get; set; }
}
public class HeroDeveloperCommand : ICommand
{
public HeroDeveloperCommand(HeroDeveloper heroDeveloper, string projectName)
{
HeroDeveloper = heroDeveloper;
ProjectName = projectName;
}
protected HeroDeveloper HeroDeveloper { get; set; }
public string ProjectName { get; set; }
public void Execute()
{
// implementation delegates work to concrete receiver
HeroDeveloper.DoAllHardWork(ProjectName);
}
}
Receiver
Team and HeroDeveloper are receivers of work that should be done.
Invoker
Customer simply aggregates many commands and without knowing how those commands were built by boss. Customer as true invoker simply triggers work using Execute method:
public class Customer
{
public Customer()
{
Commands = new List<ICommand>();
}
public void AddCommand(ICommand command)
{
Commands.Add(command);
}
protected List<ICommand> Commands { get; set; }
public void SignContractWithBoss()
{
foreach (var command in Commands)
{
command.Execute();
}
}
}
Output
User Story (Cool web site) has been completed
User Story (Ability to book beer on site) has been completed
Hero developer completed project (A) without requirements in manner of couple of hours!
UPDATE: Nov 18, 2010
UML-Diagram
Here below I added diagram showing two commands exactly as in example. Please take into account that for simplicity you can remove one pair HeroDeveloperCommand-HereDeveloper. Also take into consideration that in our example concrete commands are aggregating receivers, but this is not common situation. In most cases receiver is some another system.
November 8, 2010 Design Patterns 2 comments
Imagine that you own huge building company. It builds houses and apartment blocks all around your city. Building are of two types – either built with concrete blocks or with bricks. Since you are boss when you were deciding how to divide work you have decided that all crews will have same operations like BuildFoundation, BuildRoom, BuildRoof. But because houses are of two types you had to always keep two teams (aka. two concrete).
Once it turned out that couple of buildings were of mixed type where you had to build some rooms with concrete blocks and some with bricks. For this reason you had to move whole teams from one part of the city to another. You got many complains from your employees, they suggested moving only that part of team that is specialized in building rooms, so you can easily move small crew of workers and reassign it easily to any team instead of having two separate teams. And that is idea.
BRIDGE
Bridge is design pattern that allows you decouple realization from its abstraction, therefore your realization can be changed separately from abstraction because does not implement it directly.
In other words, our IBuildingCompany might have two concrete realizations like NearSeeBuildingCompany and CityBuildingCompany, each of them does probably something different for their foundation and roof, but at the same time we can easily and quickly reassign WallCreator crew for each of those companies to build either brick or either concrete walls.
Let say we have BuildingCompany as below:
internal interface IBuldingCompany { void BuildFoundation(); void BuildRoom(); void BuildRoof(); IWallCreator WallCreator { get; set; } } internal class BuldingCompany : IBuldingCompany { public void BuildFoundation() { Console.WriteLine("Foundation is built.{0}", Environment.NewLine); } public void BuildRoom() { WallCreator.BuildWallWithDoor(); WallCreator.BuildWall(); WallCreator.BuildWallWithWindow(); WallCreator.BuildWall(); Console.WriteLine("Room finished.{0}", Environment.NewLine); } public IWallCreator WallCreator { get; set; } public void BuildRoof() { Console.WriteLine("Roof is done.{0}", Environment.NewLine); } }
So what is so interested about it? Answer is property WallCreator, which is exactly our bridge to implementation.
Usage code
Let see this in action:
// We have two wall creating crews - concrete blocks one and bricks one var brickWallCreator = new BrickWallCreator(); var conctreteSlabWallCreator = new ConcreteSlabWallCreator(); var buildingCompany = new BuldingCompany(); buildingCompany.BuildFoundation(); buildingCompany.WallCreator = conctreteSlabWallCreator; buildingCompany.BuildRoom(); // Company can easily switch to another wall crew to continue building rooms // with another material buildingCompany.WallCreator = brickWallCreator; buildingCompany.BuildRoom(); buildingCompany.BuildRoom(); buildingCompany.BuildRoof();
Isn’t it awesome? Output should be intuitive, but since I did not show implementations of BrickWallCreator and ConcreteSlabWallCreator I’m going to list it below:
Foundation is built.
Concrete slab wall with door.
Concrete slab wall.Concrete slab wall with window.
Concrete slab wall.
Room finished.
Brick wall with door.
Brick wall.Brick wall with window.
Brick wall.
Room finished.
Brick wall with door.
Brick wall.Brick wall with window.
Brick wall.
Room finished.
Roof is done.
UML diagram illustrates how this pattern looks like and why it is called bridge.
October 3, 2010 Design Patterns No comments
VISITOR
public interface IVisitor { void Visit(OfficeBuilding building); void Visit(Floor floor); void Visit(Room room); }
public class ElectricitySystemValidator : IVisitor { public void Visit(OfficeBuilding building) { var electricityState = (building.ElectricitySystemId > 1000) ? "Good" : "Bad"; Console.WriteLine(string.Format("Main electric shield in building {0} is in {1} state.", building.BuildingName, electricityState)); } public void Visit(Floor floor) { Console.WriteLine(string.Format("Diagnosting electricity on floor {0}.", floor.FloorNumber)); } public void Visit(Room room) { Console.WriteLine(string.Format("Diagnosting electricity in room {0}.", room.RoomNumber)); } }
public class Floor : IElement { private readonly IList<Room> _rooms = new List<Room>(); public int FloorNumber { get; private set; } public IEnumerable<Room> Rooms { get { return _rooms; } } public Floor(int floorNumber) { FloorNumber = floorNumber; } public void AddRoom(Room room) { _rooms.Add(room); } public void Accept(IVisitor visitor) { visitor.Visit(this); foreach (var room in Rooms) { room.Accept(visitor); } } }
Source code elements in diagram
Usage
var floor1 = new Floor(1); floor1.AddRoom(new Room(100)); floor1.AddRoom(new Room(101)); floor1.AddRoom(new Room(102)); var floor2 = new Floor(2); floor2.AddRoom(new Room(200)); floor2.AddRoom(new Room(201)); floor2.AddRoom(new Room(202)); var myFirmOffice = new OfficeBuilding("[Design Patterns Center]", 25, 990); myFirmOffice.AddFloor(floor1); myFirmOffice.AddFloor(floor2); var electrician = new ElectricitySystemValidator(); myFirmOffice.Accept(electrician); var plumber = new PlumbingSystemValidator(); myFirmOffice.Accept(plumber);
Main electric shield in building [Design Patterns Center] is in Bad state.
Diagnosting electricity on floor 1.
Diagnosting electricity in room 100.
Diagnosting electricity in room 101.
Diagnosting electricity in room 102.
Diagnosting electricity on floor 2.
Diagnosting electricity in room 200.
Diagnosting electricity in room 201.
Diagnosting electricity in room 202.
Plumbing state of building [Design Patterns Center] probably is in Good condition, since builing is New.
Diagnosting plumbing on floor 1.
Diagnosting plumbing on floor 2.
Classic UML diagram
September 26, 2010 C#, Design Patterns, Java, Opinion, Personal, Success 12 comments
Yeah, title sounds not logically, but you will understand in a few why it is still relevant to this blog post.
It was and it is a good idea to…
In one of my blog posts I’ve decided to have all of the GoF Design Patterns written with Java. And idea itself is very good. Having all of the design patterns written by your own with you own examples gives you understanding of the DP that you cannot gain anywhere else plus to that if you have industrial experience of using all of them you can start think that you are guru of DP.
Process of writing my post on one of the Design Patterns looks like this: I read chapter of the GoF book on the particular DP, then I think up my own example if I do not have it already in my mind and after I’m done with some preliminary ideas I search over the internet for interesting articles on it and probably rethink some of the aspects of my example. After all of that I proceed to writing blog post and source code with Java.
Conclusion: Awesome and probably one of the best ways of learning DP is to have your own example of using it and industrial experience.
Design Patterns articles
One of the intents of having DP written in Java was to familiarize with that language. But it turns out that I did not learn much from Java (except of few things). Also few months ago I started keeping up Tuesday’s Design Pattern on the Lviv .NET User Group Page. Since it is .NET specific UG, I used to do following: 1) translate and 2) translate. In first place it is translation from English to Ukrainian and in second from Java to C#. When with item number one I have to apply some logic and rephrasing I cannot say the same about second item. I just copy code-paste code into Visual Studio and change few keywords. So what do I learn regarding of Java in this case?
I will continue learning Java, but I have to consider better way of doing it. I will also continue writing about Design Patterns, but with examples in C#.
Conclusion: Learning another programming language (Java) is really great idea, but be sure that you choose right approach of doing this.
First free e-book
On the road to Lviv I got perfect idea to start my first book. Of course this cannot be comprehensive stunning author’s book, but I have to start with something. In other words some probing book and this could be this “try it” case. I’m almost sure that there are no books about GoF Design Patterns in Ukrainian. (I suppose that there are in Russian, which can be easily understandable for most Ukrainians…)
How this book will be different?
Why do I need it?
I understand that this book might not be popular at all. But I have to start with something and plus to this it will help me familiarize with the whole process and build my confidence for future.
Also if you have some doubts about my idea I have a question for you: “Have you ever dreamt about your own book? If yes, do you have at least small book written?”
Conclusion: Never be skeptic about starting your first book. It might be a huge step to your success as anything else you are hesitating about but still dreaming about it!
July 25, 2010 Design Patterns 4 comments
Imagine that your application is very complicated and it happened that you use two logging providers – one is Log4J and another is Java Logging. Your co-worker got great idea to have specification of which of the providers to use in configuration file. As you wrap all logging logic behind some ILogger interface, you also want to hide exact logging provider from client code and pass creating logic to some separate class.
For me this design patter is the most familiar and easiest. I’m sure that most of the readers have seen it many times. So the intent of the Factory Method is to hide exact class that should be created basing on some conditions.
In our example classes that should be created are Log4J or JavaLogging, they both implement interface ILogger, that is widely used in your application.
As you already guess it might be that in future you will decide to use another logging provider. As we already described in our scenario we read which logging provider to use from some configuration. For not exposing exact classes we delegate this work to LoggerProviderFactory. Here is usage:
ILogger logger = LoggerProviderFactory.GetLoggingProvider(providerType);
logger.LogToConsole(“Hello Factory Method Design Pattern.”);
}
private LoggerProviderFactory.LoggingProviders getTypeOfLoggingProviderFromConfigFile() {
return LoggerProviderFactory.LoggingProviders.Log4J;
}
What we are getting back from GetLoggingProvider method is interface. Factory Method decides which of the concretes return basing on the input parameter, which in our case is enum.
Here is implementation of Factory Method:
public enum LoggingProviders{
JavaLogging,
Log4J
}
// this is our factory method…
public static ILogger GetLoggingProvider(LoggingProviders logProviders)
{
switch(logProviders){
case JavaLogging:
return new JavaLogging();
case Log4J:
return new Log4J();
default:
return new JavaLogging();
}
}
}
Because my hardcoded configuration logic returns me Log4J and since implementation of LogToConsole of Log4J concrete logger looks like:
I’m getting this as output: Log4J: Hello Factory Method Design Pattern.
Here is my drawing try:
If you liked or disliked this blog post, just let me know.
July 24, 2010 Design Patterns, Java 1 comment
Have you worked with Outlook calendar or any other mature calendar, that allows you copy some events from day to day?
For example your friend scheduled small beer party for Friday, 23 July where he listed his friends, also he allocated time from 7pm till 3 am and put high priority, he also described that it is great to have party on Friday after work in the comments. As you were invited, party went extremely well. In the end of party your friend decided to schedule similar party for the next Friday, but since he had already drunk too much it was complicated for him to populate all of the fields of the event in calendar. Which kind of enhancement would you propose for the calendar, your friend uses? Probably copy-paste functionality.
Prototype is design pattern, that allows us create complete copies of instances already defined in design (list of possible types of events) or either run-time(Friday’s event), so we no longer need reinstantiate them from A to Z. Already defined instances are called prototypical instances.
As we already described one applicability of Prototype for copying instances specified at run-time, this design pattern could be also used for reducing number of subclasses in the system. For example instead of having subclasses like “5 floors apartment block with 3 rooms flats“, “9 floors apartment block with 2-3-4 rooms flats” and “12 floors apartment block with 1-2-3 rooms flats” you may have 3 instances of ApartmentBlock initialized with needed properties, and then you just copy one of them when you need to build new building somewhere in the city. In other words no need to write either this “new ApBlockWith9FloorsAnd234Flats()” or this “new ApartmentBlock(){Floors = 9; FlatsDic = {2,3,4}}“.
What you need is something like “_9FloorsApBlock.Clone()“. Of course you can combine this with FactoryMethod, so you will have something like “GetMe9FloorsAppBlock()“, which inside calls cloning of prototypical instance.
Example
Let’s now take a look at Prototype, which defines clone() method for our prototypes.
My concrete Prototype class is calendar event, which looks like this:
Client code is executed, when my friend wants to open calendar, right click on event and paste it into other location, therefor changing start/end date & time.
Take a look on this process:
public CalendarEvent getExistingEvent(){
CalendarEvent beerParty = new CalendarEvent();
ArrayList<Attendee> friends = new ArrayList<Attendee>();
Attendee andriy = new Attendee();
andriy.FirstName = “Andriy”;
andriy.LastName = “Buday”;
friends.add(andriy);
beerParty.set_attendees(friends);
beerParty.set_startDateAndTime(new Date(2010,7,23,19,0,0));
beerParty.set_priority(Priority.High());
return beerParty;
}
public void Run() throws CloneNotSupportedException {
CalendarEvent beerParty = getExistingEvent();
CalendarEvent nextFridayEvent = (CalendarEvent) beerParty.clone();
nextFridayEvent.set_startDateAndTime(new Date(2010,7,30,19,0,0));
// we will talk about further code a bit later
nextFridayEvent.get_attendees().get(0).EmailAddress = “andriybuday@liamg.com”;
nextFridayEvent.get_priority().setPriorityValue(0);
if(beerParty.get_attendees() != nextFridayEvent.get_attendees())
{
System.out.println(“GOOD: Each event has own list of attendees.”);
}
if(beerParty.get_attendees().get(0).EmailAddress == nextFridayEvent.get_attendees().get(0).EmailAddress)
{
//In this case it is good to have shallow copy of the attendees.
System.out.println(“GOOD: If I updated my e-mail address it will be updated in all events.”);
}
if(beerParty.get_priority().isHigh() != nextFridayEvent.get_priority().isHigh())
{
System.out.println(“GOOD: Each event should have own priority object, fully-copied.”);
}
}
}
As you can see my friend got copy of the existing event and by grag-drop changed its date. But after that I noticed that I can change my address in his attendees list, so I did that, also after we got another beer and felt sick we decided to lower priority to neutral with this line: nextFridayEvent.get_priority().setPriorityValue(0);
Looks like we’ve got what we want – copy of the existing event, with attendees, priority, etc. But it turns out that when I open old event I see that priority is now neutral, not high. As you already guessed that is because we executed shallow copy.
Shallow copy copies only direct value field and keeps same references.
Deep copy copies whole graph of objects, so they all have different addresses in heap.
CLONE
For Prototype we can implement clone() our own way, so for example I can have partially deep copy, so my new address should be the same in all events, but priority should keep different.
In Prototype design pattern we implement clone method. Sometimes we may need complete deep copy which can be archived by manual copying which is cumbersome, by reflection, which could be slow, or by serializing and deserializing to new object, which is also expensive. But sometimes you need partial deep copying like in our example. That is why programming languages introduces Cloneable interfaces to be implemented by our own. Suitalbe for our example could look like:
// we also would like to copy priority
copy.set_priority(this.get_priority().clone());
return copy;
}
I already wrote console outputs that say we are ok. But also here is screenshot from debug mode to prove that I do not cheat:
Hope this article wasn’t boring and brought more understanding of Prototype design pattern. Please let me know what you think about it!
Here is my Design Patterns Table.
July 2, 2010 Design Patterns 2 comments
If you ever played any shooter game, you probably know what do hot-keys F5 & F9 mean. If you did not play those anyway you should be aware of usefulness of quick-save/quick-load functionality. By pressing F5 you save your current location your health/armor levels and maybe some other information, like how many monsters did you kill already. This defines your state which is going to be saved. On pressing F9 you return to your previous saved state (kind of undo operation).
When you are saving your state you don’t wanna it to be accessible by other classes (encapsulation of state), so you will be sure that none will decrease you health level. Also you wanna keep track of savings and maybe you are going to add functionality that will get back through two-three saves by pressing Shift+F9 (+F9).
How can you accomplish this?
Memento pattern is used when you want do undo operations without exposing internal state of the Originator (Game). Coordination of operations is done by Caretaker, or something that simply lists mementos and therefore remembers states without knowing what are they.
Let’s take a look at implementation:
Originator (Game)
public
GameMemento gameSave(){
return
new
GameMemento(_state);
}
public void loadGame(GameMemento memento){
_state = memento.getState();
}
public class
GameMemento {
private
final
GameState _state;
private GameMemento(GameState state) {
_state = state;
}
private GameState getState(){
return
_state;
}
}
}
So it is able to generate memento instance with current game state, as well it is able to get state from existing memento, BUT none else could get that state, since GameMemento is inner class of Game and methods are private.
Caretaker
Or the guy, who keeps track of your F5/F9th. Currently it is able to load the latest one quick save, but it could be easily enhanced.
public
Caretaker() {
_game = new
GameOriginator();
}
public void
shootThatDumbAss(){
_game.Play();
}
public void F5(){
_quickSaves.push(_game.gameSave());
}
public void F9(){
_game.loadGame(_quickSaves.peek());
}
}
Output
With following usage code:
our application generates:
Health: 100
Killed Monsters: 0
Health: 90
Killed Monsters: 2
Health: 81
Killed Monsters: 4
Health: 72
Killed Monsters: 6
Health: 64
Killed Monsters: 8
Health: 90
Killed Monsters: 2
Here is quick UML, that I drew for my example:
April 14, 2010 Design Patterns, Refactoring 2 comments
Another colleague brought me present today – the blog post. Thank you. You were right!
We will do some refactoring which will lead us from Anti-Pattern to Pattern. From Sequential Coupling to Template Method. And as I see it could be very common way to refactor bad code that represents mentioned anti-pattern.
So, lets start with the following question. What do you see to be wrong with following code?
Manager is very angry guy and he needs to get the project done. For that he would like to get some worker, which implements IWorker interface, and delegate some work to him. But also manager knows that worker could be new to project so it will require do go ahead and to some preparational work before and maybe something to do after work is done…
What is wrong? Answer is that Manager cares too much about how worker should organize his work. Why should manager know that worker needs to be prepared for work? What do we have here is the Sequential Coupling anti-pattern.
(My definition)
If we call Work and then PreWork, code could be broken. And we want to prevent this. For example, we can move all that stuff in one method – Work, but also sometimes it is needed to perform pre or/and after work, but sometimes not. That is why we had following design that allowed us do this. See that StandardWorker doesn’t need do something after he has finished. This was achieved with virtual and abstract methods.
So, what we need to do is to hide the order in which we call methods, be sure that order remains the same, and still have possibility to override each of method. What I just described is Template Method.
In our example we could leave one method in interface, then implement it in base class with calling everything else we need in correct order, each of those things we call could be overridden, we left them protected to do not show to the world.
It really looks for me that it could be common to perform refactoring from Sequential Coupling to Template Method. Hope you liked this post.