23

Ruby Patterns

Embed Size (px)

DESCRIPTION

Ruby patterns

Citation preview

  • 1. Introduction2. Adapter3. Builder4. Command5. Composite6. Decorator7. Factory8. Iterator9. Observer

    10. Proxy11. Singleton12. State13. Strategy14. Template

    TableofContents

    RubyPatterns

    2

  • ExamplesofPatternsinRuby

    1. Adapter2. Builder3. Command4. Composite5. Decorator6. Factory7. Iterator8. Observer9. Proxy

    10. Singleton11. State12. Strategy13. Template

    RubyPatterns

    TableofContents

    RubyPatterns

    3Introduction

  • Converttheinterfaceofaclassintoanotherinterfaceclientsexpect.Adapterletsclassesworktogetherthatcouldn'totherwisebecauseofincompatibleinterfaces.

    classQuestattr_accessor:difficulty,:hero

    definitialize(difficulty)@difficulty=difficulty@hero=nilend

    [email protected]+=calculate_experienceend

    defcalculate_experience@difficulty*50/@hero.levelendend

    classHeroattr_accessor:level,:exp,:quests

    definitialize@level=1@exp=0@quests=[]end

    deftake_quest(quest)@quests

  • attr_accessor:hero

    definitialize(old_quest,difficulty)@old_quest=old_quest@old_quest.difficulty=difficulty@hero=nilend

    [email protected]+=@old_quest.doneendend

    #Usagehero=Hero.newquest=Quest.new5hero.take_questquesthero.finish_questquestputshero.exp#=>250some_old_quest=OldQuest.newold_quest_adapted=QuestAdapter.new(some_old_quest,5)hero.take_questold_quest_adaptedhero.finish_questold_quest_adaptedputshero.exp#=>300

    RubyPatterns

    5Adapter

  • Separatetheconstructionofacomplexobjectfromitsrepresentationsothatthesameconstructionprocesscancreatedifferentrepresentations.

    classBoardBuilderdefinitialize(width,height)@[email protected][email protected][email protected]=[]@board.monsters=[]end

    defadd_tiles(n)n.times{@board.tiles2builder.add_tiles(3)builder.add_monsters(2)putsboard.tiles.size#=>3putsboard.monsters.size#=>2

    Builder

    RubyPatterns

    6Builder

  • Encapsulatearequestasanobject,therebylettingyouparameterizeclientswithdifferentrequests,queueorlogrequests,andsupportundoableoperations.

    classTurndefinitialize@commands=[]enddefrun_command(command)command.execute@commands

  • #Usagehero=Hero.newget_money=GetMoneyCommand.newheroheal=HealCommand.newheroturn=Turn.newturn.run_command(heal)putshero.health#=>110turn.run_command(get_money)putshero.money#=>10turn.undo_commandputshero.money#=>0

    RubyPatterns

    8Command

  • Compositionoverinheritance.Composeobjectsintotreestructurestorepresentpart-wholehierarchies.

    classCompositeQuestdefinitialize@tasks=[]end

    def

  • RubyPatterns

    10Composite

  • Attachadditionalresponsibilitiestoanobjectdynamically.Decoratorsprovideaflexiblealternativetosubclassingforextendingfunctionality.

    classItemDecoratordefinitialize(item)@item=itemend#[email protected]

    classMagicItemDecoratorItemMagic

    Decorator

    RubyPatterns

    11Decorator

  • masterpiece_item=MasterpieceItemDecorator(item)putsmasterpiece_item.price#=>20putsmasterpiece_item.description#=>ItemMasterpiece

    #allnextlinesputs"dosomething"item.usemagic_item.usemasterpiece_item.use

    RubyPatterns

    12Decorator

  • Defineaninterfaceforcreatinganobject,butletsubclassesdecidewhichclasstoinstantiate.

    classPartyattr_reader:membersdefinitialize(factory)@members=[]@factory=factoryend

    defadd_warriors(n)n.times{@members2

    Factory

    RubyPatterns

    13Factory

  • Iteratorhelpsyoutoiteratethroughacomplexobjectusinganinteratormethod.

    classParentattr_reader:first_name

    definitialize(first_name,gender)@first_name=first_name@gender=genderendend

    classChild6putshero.cursed?#=>true

    RubyPatterns

    16Observer

  • Provideasurrogateorplaceholderforanotherobjecttocontrolaccesstoit.

    classHeroattr_accessor:keywords

    definitialize@keywords=[]endend

    classComputerProxy#Forwardableallowsobjectstorunmethodsonbehalf#ofit'smembers,inthiscasetheComputerobjectextendForwardable

    #WedelegatetheComputerProxy'suseof#theComputerobject'saddmethoddef_delegators:real_object,:add

    definitialize(hero)@hero=heroend

    defexecutecheck_accessreal_object.executeend

    [email protected]?(:computer)raise"Youhavenoaccess"endend

    defreal_object@real_object||=Computer.newendend

    classComputerdefinitialize@queue=[]end

    defadd(command)@queue

  • hero=Hero.newproxy=ComputerProxy.new(hero)proxy.add("somecommand")proxy.execute#=>raiseerrorhero.keywordsexecutingcommands

    RubyPatterns

    18Proxy

  • Defineauniqueinstanceofanobject.

    classHeroFactory@@instance=nil

    defself.instance@@instance||=HeroFactory.send(:new)end

    defcreate_warriorWarrior.newend

    defcreate_mageMage.newend

    private_class_method:newend

    #Usagefactory=HeroFactory.instanceanother_factory=HeroFactory.instanceputsfactory==another_factory#=>trueHeroFactory.new#=>RaiseException

    Singleton

    RubyPatterns

    19Singleton

  • Thispatterntriestosimplifycomplicatedcontrolflowschanginganobject'sbehaviordynamically.

    classOperationattr_reader:statedefinitialize@state=OperationOpenState.newend

    deftrigger(state)@[email protected](state)endend

    classOperationOpenStatedefnext(state)valid?(state)?OperationPendingPaymentState.new:raiseIllegalStateJumpErrorend

    defvalid?(state)state==:pending_paymentendend

    classOperationPendingPaymentStatedefnext(state)OperationConfirmState.newifvalid?(state)end

    defvalid?(state)state==:confirmendendclassIllegalStateJumpErrorOperationOpenStateoperation.trigger:pending_paymentputsoperation.state.class#=>OperationPendingPaymentStateoperation.trigger:confirmputsoperation.state.class#=>OperationConfirmState

    operation=Operation.newoperation.trigger:confirm#=>raiseIllegalStateJumpError

    State

    RubyPatterns

    20State

  • Defineafamilyofalgorithms,encapsulateeachone,andmaketheminterchangeable.

    classHeroattr_reader:damage,:health,:skillsattr_accessor:printer

    definitialize(printer)@damage=10@health=5@printer=printer@skills=[:stealth,:driving,:intimidation]end

    defprint_statsifblock_given?yield(damage,health,skills)elseprinter.print(damage,health,skills)endendend

    classBattleStatsdefprint(damage,health,skills)"Damage:#{damage}\nHealth:#{health}"endend

    classSkillStatsdefprint(damage,health,skills)skills.inject(""){|result,skill|result+skill.to_s.capitalize+"\n"}endend

    #UsageHero.new(BattleStats.new)Hero.print_stats#=>Damage:10#Health:5

    Hero.new(SkillStats.new)Hero.print_stats#=>Stealth#Driving#Intimidation

    Hero.new(any_printer)Hero.print_statsdo|damage,health,skills|"Looks:I'mprintingacustomizemessageaboutmyherowithdamage#{damage}andnumberofskills:end

    Strategy

    RubyPatterns

    21Strategy

  • Definetheskeletonofanalgorithminanoperation,deferringsomestepstosubclasses.Templatemethodsletssubclassesredefinecertainstepsofanalgorithmwithoutchangingthealgorithm'sstructure.

    classHeroattr_reader:damage,:abilities

    definitialize@damage=damage_rating@abilities=occupation_abilitiesend

    defgreetgreeting=["Hello"]greeting

  • defoccupation_abilities[:magic_spell]end

    defunique_greeting_line"Mageisreadytomakepowerfulspells!"endend

    RubyPatterns

    23Template

    IntroductionAdapterBuilderCommandCompositeDecoratorFactoryIteratorObserverProxySingletonStateStrategyTemplate