├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── README.zh.md ├── ref ├── article1.md ├── design-patterns.md ├── metaclass.md ├── principles.md ├── uml1.png ├── uml2.png └── uml3.png └── src ├── Makefile ├── Makefile.template ├── Readme.md ├── abstract-factory ├── abstract-factory.md ├── cpp │ ├── Makefile │ ├── button.cc │ ├── button.h │ ├── factory.cc │ ├── factory.h │ ├── main.cc │ ├── text.cc │ └── text.h ├── perl │ ├── Factory.pm │ ├── Factory │ │ ├── FactoryA.pm │ │ └── FactoryB.pm │ ├── Product.pm │ ├── ProductA.pm │ ├── ProductA │ │ ├── ProductA1.pm │ │ └── ProductA2.pm │ ├── ProductB.pm │ ├── ProductB │ │ ├── ProductB1.pm │ │ └── ProductB2.pm │ └── test.pl ├── php │ └── factory.php ├── python │ └── test.py └── uml.png ├── adapter ├── adapter.md ├── cpp │ ├── Makefile │ ├── adapter.cc │ ├── adapter.h │ └── main.cc ├── perl │ ├── Adapter.pm │ ├── Animal.pm │ ├── Animal │ │ ├── Cat.pm │ │ └── Dog.pm │ └── test.pl ├── php │ ├── adapter.php │ └── test.php ├── python │ └── test.py ├── uml1.png └── uml2.png ├── add-pattern.sh ├── bridge ├── bridge.md ├── cpp │ ├── Makefile │ ├── bridge.cc │ ├── bridge.h │ └── main.cc ├── perl │ ├── Abstraction.pm │ ├── Abstraction │ │ └── RefinedAbstraction.pm │ ├── Implementator.pm │ ├── Implementator │ │ ├── ConcreteImplementatorA.pm │ │ └── ConcreteImplementatorB.pm │ └── test.pl ├── php │ └── bridge.php ├── python │ └── test.py └── uml.png ├── builder ├── builder.md ├── cpp │ ├── Makefile │ ├── builder.cc │ ├── builder.h │ ├── director.cc │ ├── director.h │ └── main.cc ├── perl │ ├── Builder.pm │ ├── Builder │ │ └── ConcreteBuilder.pm │ ├── Director.pm │ ├── Product.pm │ └── test.pl ├── php │ └── builder.php ├── python │ └── test.py ├── ruby │ └── address.rb └── uml.png ├── chain-of-responsibility ├── chain-of-responsibility.md ├── cpp │ ├── handler.cc │ ├── handler.h │ ├── main.cc │ └── makefile ├── perl │ ├── Handler.pm │ ├── Handler │ │ ├── ConcreteHandler1.pm │ │ ├── ConcreteHandler2.pm │ │ └── ConcreteHandler3.pm │ └── test.pl ├── php │ └── test.php ├── python │ └── test.py ├── uml1.png └── uml2.png ├── command ├── command.md ├── cpp │ ├── Makefile │ ├── command.cc │ ├── command.h │ └── main.cc ├── perl │ ├── Command.pm │ ├── Command │ │ ├── CopyCommand.pm │ │ ├── MacroCommand.pm │ │ ├── MacroCommand │ │ │ └── DemoMacroCommand.pm │ │ └── PasteCommand.pm │ ├── Invoker.pm │ ├── Receiver.pm │ └── test.pl ├── php │ ├── command.php │ └── test.php ├── python │ └── test.py ├── ruby │ └── test.rb ├── uml1.png └── uml2.png ├── composite ├── composite.md ├── composite.png ├── composite2.png ├── cpp │ ├── Makefile │ ├── composite.cc │ ├── composite.h │ └── main.cc ├── perl │ ├── Component.pm │ ├── Component │ │ ├── Composite.pm │ │ └── Leaf.pm │ └── test.pl ├── php │ ├── composite.php │ └── test.php ├── python │ └── test.py ├── ruby │ └── test.rb └── uml.png ├── decorator ├── cpp │ ├── Makefile │ ├── decorator.cc │ ├── decorator.h │ └── main.cc ├── decorator.md ├── perl │ ├── AddStamp.pm │ └── decorated.pl ├── php │ └── decorator.php ├── python │ ├── test.py │ └── test2.py ├── ruby │ └── test.rb └── uml.png ├── facade ├── cpp │ ├── Makefile │ └── main.cc ├── facade.md ├── perl │ ├── FileSys.pm │ ├── FileSys │ │ ├── AntiVirus.pm │ │ ├── Encryptor.pm │ │ └── Zipper.pm │ └── test.pl ├── php │ └── facade.php ├── python │ └── test.py ├── ruby │ └── test.rb ├── uml1.png ├── uml2.png └── uml3.png ├── factory-method ├── cpp │ ├── Makefile │ ├── factory.h │ ├── lumia920factory.cc │ ├── lumia920factory.h │ ├── main.cc │ ├── nokia.cc │ └── nokia.h ├── factory-method.md ├── factory.png ├── perl │ ├── Factory.pm │ ├── Factory │ │ └── LumiaFactory.pm │ ├── Nokia │ ├── Nokia.pm │ └── test.pl ├── php │ └── factory.php ├── python │ └── test.py ├── uml1.png └── uml2.png ├── factory.cc ├── flyweight ├── cpp │ ├── Makefile │ ├── flyweight.cc │ ├── flyweight.h │ └── main.cc ├── flyweight.md ├── perl │ ├── Flyweight.pm │ ├── Flyweight │ │ ├── ConcreteFlyweight.pm │ │ └── UnsharedConcreteFlyweight.pm │ ├── FlyweightFactory.pm │ └── test.pl ├── php │ ├── Readme.md │ ├── cflyweight.php │ ├── flyweight.php │ └── flyweight.png ├── python │ └── test.py └── uml.png ├── interpreter ├── cpp │ ├── Makefile │ ├── expression.cc │ ├── expression.h │ └── main.cc ├── interpreter.md ├── perl │ ├── Expression.pm │ ├── Expression │ │ ├── Char.pm │ │ └── Num.pm │ ├── Interpreter.pm │ └── test.pl ├── php │ └── test.php ├── uml.png └── uml_java.png ├── iterator ├── cpp │ ├── Makefile │ └── main.cc ├── iterator.md ├── perl │ ├── Iterator.pm │ ├── dir.pl │ ├── file.pl │ ├── format.pl │ ├── glob.pl │ ├── hash.pl │ ├── match.pl │ ├── permute.pl │ └── upto.pl ├── python │ └── test.py ├── ruby │ └── test.rb ├── uml1.png └── uml2.png ├── java ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── errpro │ │ └── design_patterns │ │ ├── abstract_factory │ │ ├── ConcreteFactory1.java │ │ ├── ConcreteFactory2.java │ │ ├── Factory1.java │ │ ├── Factory2.java │ │ ├── ProductA.java │ │ ├── ProductA1.java │ │ ├── ProductA2.java │ │ ├── ProductB.java │ │ ├── ProductB1.java │ │ ├── ProductB2.java │ │ └── Test.java │ │ ├── adapter │ │ ├── Adaptee.java │ │ ├── Adapter.java │ │ ├── Target.java │ │ └── Test.java │ │ ├── bridge │ │ ├── Abstraction.java │ │ ├── ConcreteImplementorA.java │ │ ├── ConcreteImplementorB.java │ │ ├── Implementor.java │ │ ├── RefinedAbstraction.java │ │ └── Test.java │ │ ├── builder │ │ ├── AbstractBuilder.java │ │ ├── Director.java │ │ ├── KFCBuilder.java │ │ ├── MCDBuilder.java │ │ └── Test.java │ │ ├── chain_of_responsibility │ │ ├── AbstractHandler.java │ │ ├── AbstractRequest.java │ │ ├── Handler01.java │ │ ├── Handler02.java │ │ ├── Handler03.java │ │ ├── Levels.java │ │ ├── Request01.java │ │ ├── Request02.java │ │ ├── Request03.java │ │ └── Test.java │ │ ├── command │ │ ├── Command.java │ │ ├── CommandChange.java │ │ ├── CommandOff.java │ │ ├── CommandOn.java │ │ ├── ConcreteCommand.java │ │ ├── Control.java │ │ ├── Invoker.java │ │ ├── Receiver.java │ │ ├── TV.java │ │ └── Test.java │ │ ├── composite │ │ ├── Developer.java │ │ ├── Employee.java │ │ ├── Manager.java │ │ └── Test.java │ │ ├── decorator │ │ ├── Component.java │ │ ├── ConcreteComponent.java │ │ ├── ConcreteDecorator.java │ │ ├── Decorator.java │ │ └── Test.java │ │ ├── facade │ │ ├── OperatorWrapper.java │ │ └── Test.java │ │ ├── factory_method │ │ ├── ConcreteCreator1.java │ │ ├── ConcreteCreator2.java │ │ ├── ConcreteProductA.java │ │ ├── ConcreteProductB.java │ │ ├── Creator.java │ │ ├── Product.java │ │ └── Test.java │ │ ├── flyweight │ │ ├── ConcreteFont.java │ │ ├── Font.java │ │ ├── FontInner.java │ │ ├── FontInnerFactory.java │ │ └── Test.java │ │ ├── interpreter │ │ ├── AddExpression.java │ │ ├── Calculator.java │ │ ├── Client.java │ │ ├── Expression.java │ │ ├── SubExpression.java │ │ ├── SymbolExpression.java │ │ └── VarExpression.java │ │ ├── mediator │ │ ├── Colleague.java │ │ ├── ConcreteColleague1.java │ │ ├── ConcreteColleague2.java │ │ ├── ConcreteMediator.java │ │ └── Test.java │ │ ├── memento │ │ ├── GameRole.java │ │ ├── RoleMemoManager.java │ │ ├── RoleStateMemo.java │ │ └── Test.java │ │ ├── observer │ │ ├── ConcreteObserver.java │ │ ├── ConcreteSubject.java │ │ ├── Observer.java │ │ ├── Subject.java │ │ └── Test.java │ │ ├── prototype │ │ ├── Prototype.java │ │ └── Test.java │ │ ├── proxy │ │ ├── ProxySubject.java │ │ ├── RealSubject.java │ │ └── Subject.java │ │ ├── simple_factory │ │ ├── Test.java │ │ ├── User.java │ │ ├── UserDB2Dao.java │ │ ├── UserDao.java │ │ ├── UserDaoFactory.java │ │ ├── UserOracleDao.java │ │ └── build.xml │ │ ├── singleton │ │ └── Singleton.java │ │ ├── state │ │ ├── IndexServerlet.java │ │ └── Test.java │ │ ├── strategy │ │ ├── Computer.java │ │ ├── EnergySavingStrategy.java │ │ ├── HighPerformanceStrategy.java │ │ ├── MediumStrategy.java │ │ ├── PowerStrategy.java │ │ └── Test.java │ │ ├── template │ │ ├── Template.java │ │ └── TemplateImpl.java │ │ └── visitor │ │ ├── Failure.java │ │ ├── Love.java │ │ ├── Man.java │ │ ├── Person.java │ │ ├── Success.java │ │ ├── Test.java │ │ ├── Visitor.java │ │ └── Woman.java │ └── test │ └── java │ └── com │ └── errpro │ └── design_patterns │ └── singleton │ └── SingletonTest.groovy ├── main.cc.template ├── mediator ├── cpp │ ├── Makefile │ ├── country.cc │ ├── country.h │ ├── main.cc │ ├── mediator.cc │ └── mediator.h ├── mediator.md ├── perl │ ├── Colleague.pm │ ├── Mediator.pm │ ├── colleague │ │ ├── ConcreteColleague1.pm │ │ └── ConcreteColleague2.pm │ ├── mediator │ │ └── ConcreteMediator.pm │ └── test.pl ├── php │ └── test.php ├── python │ └── test.py ├── uml1.png └── uml2.png ├── memento ├── cpp │ ├── Makefile │ ├── main.cc │ ├── memento.cc │ ├── memento.h │ ├── originator.cc │ └── originator.h ├── memento.md ├── perl │ ├── Caretaker.pm │ ├── Memento.pm │ ├── Originator.pm │ └── test.pl ├── php │ └── memento.php ├── python │ └── memento.py └── uml.png ├── null-object ├── cpp │ ├── Makefile │ ├── animal.cc │ ├── animal.h │ └── main.cc ├── null-object.md ├── php │ ├── Logger.php │ ├── NullLogger.php │ ├── PrintLogger.php │ └── Service.php ├── python │ └── null.py └── ruby │ ├── NullObject.rb │ └── test.rb ├── object-pool ├── object-pool.md └── python │ └── pool.py ├── observer ├── cpp │ ├── Makefile │ ├── main.cc │ ├── observer.cc │ ├── observer.h │ ├── subject.cc │ └── subject.h ├── observer.md ├── perl │ ├── Observer.pm │ ├── Observer │ │ └── DataObserver.pm │ ├── Subject.pm │ ├── Subject │ │ └── DataSubject.pm │ └── test.pl ├── php │ ├── client.php │ ├── observer.php │ └── subject.php ├── python │ └── test.py ├── ruby │ ├── car.rb │ ├── notifier.rb │ └── test.rb ├── uml1.png ├── uml2.png └── uml3.png ├── private-class-data ├── cpp │ ├── Makefile │ └── main.cc └── private-class-data.md ├── prototype ├── cpp │ ├── Makefile │ ├── main.cc │ ├── prototype.cc │ └── prototype.h ├── perl │ ├── ProtoType.pm │ ├── ProtoType │ │ └── ConcreteProtoType.pm │ └── test.pl ├── php │ └── prototype.php ├── prototype.md ├── python │ └── test.py └── uml.png ├── proxy ├── cpp │ ├── Makefile │ ├── main.cc │ ├── proxy.cc │ └── proxy.h ├── perl │ ├── Proxy.pm │ ├── Subject.pm │ ├── Subject │ │ ├── Proxy.pm │ │ └── RealSubject.pm │ └── test.pl ├── php │ └── proxy.php ├── proxy.md ├── python │ ├── implementation.py │ ├── proxy.py │ └── test.py └── uml.png ├── simple-factory ├── cpp │ ├── Makefile │ ├── factory.cc │ ├── factory.h │ ├── main.cc │ ├── nokia.cc │ └── nokia.h ├── factory.cc ├── perl │ ├── Factory.pm │ ├── Nokia.pm │ ├── Nokia │ │ ├── Lumia.pm │ │ └── Symbian.pm │ └── test.pl ├── php │ └── test.php └── simple-factory.md ├── singleton ├── TODO ├── cpp │ ├── Makefile │ ├── main.cc │ ├── singleton.cc │ └── singleton.h ├── perl │ ├── Singleton.pm │ └── main.pl ├── php │ └── Singleton.php ├── python │ ├── borg.py │ ├── singleton.py │ └── test.py ├── ruby │ ├── appconfig.rb │ └── test.rb └── singleton.md ├── state ├── cpp │ ├── Makefile │ ├── main.cc │ ├── state.cc │ └── state.h ├── perl │ ├── Context.pm │ ├── State.pm │ ├── State │ │ ├── ConcreteStateA.pm │ │ └── ConcreteStateB.pm │ └── test.pl ├── php │ ├── client.php │ ├── context.php │ └── state.php ├── python │ ├── state.py │ ├── test.py │ └── work.py ├── state.md ├── uml1.png └── uml2.png ├── strategy ├── cpp │ ├── Makefile │ └── main.cc ├── perl │ ├── Algorithm.pm │ ├── Algorithm │ │ ├── DES.pm │ │ └── RSA.pm │ ├── Context.pm │ └── test.pl ├── php │ └── strategy.php ├── python │ └── strategy.py ├── strategy.md ├── uml1.png └── uml2.png ├── template ├── cpp │ ├── Makefile │ ├── class.cc │ ├── class.h │ └── main.cc ├── perl │ ├── AbstractClass.pm │ ├── AbstractClass │ │ └── ConcreteClass.pm │ └── test.pl ├── php │ └── test.php ├── python │ └── test.py ├── template.md └── uml.png ├── test.perl.template └── visitor ├── cpp ├── Makefile ├── main.cc ├── seed.cc ├── seed.h ├── status.cc └── status.h ├── perl ├── Corporation.pm ├── Corporation │ ├── CorporationA.pm │ └── CorporationB.pm ├── Visitor.pm ├── Visitor │ ├── VisitorA.pm │ └── VisitorB.pm └── test.pl ├── php ├── client.php ├── corporation.php └── visitor.php ├── python └── test.py ├── ruby └── test.rb ├── uml1.png ├── uml2.png └── visitor.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled python and java class files 7 | *.pyc 8 | *.class 9 | 10 | # Compiled Dynamic libraries 11 | *.so 12 | *.dylib 13 | 14 | # Compiled Static libraries 15 | *.lai 16 | *.la 17 | *.a 18 | 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | script: 4 | - cd src/java && mvn test 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | dist: 2 | make clean 3 | @sdir=`pwd`; sdir=$${sdir##*/}; \ 4 | cd .. && tar --exclude $${sdir}/.git \ 5 | -czf $${sdir}.tar.gz $${sdir} 6 | 7 | clean: 8 | $(MAKE) -C src clean 9 | 10 | .PHONY: dist clean 11 | -------------------------------------------------------------------------------- /ref/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/ref/uml1.png -------------------------------------------------------------------------------- /ref/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/ref/uml2.png -------------------------------------------------------------------------------- /ref/uml3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/ref/uml3.png -------------------------------------------------------------------------------- /src/Makefile.template: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | 5 | $(TARGET): $(OBJS) 6 | $(CXX) $^ -o $@ 7 | 8 | clean: 9 | $(RM) $(OBJS) $(TARGET) 10 | -------------------------------------------------------------------------------- /src/Readme.md: -------------------------------------------------------------------------------- 1 | #Designe Patterns Implemetation in several languages 2 | -------------------------------------------------------------------------------- /src/abstract-factory/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | CXXFLAGS += -std=c++11 3 | OBJS := main.o \ 4 | button.o \ 5 | text.o \ 6 | factory.o \ 7 | 8 | $(TARGET): $(OBJS) 9 | $(CXX) $^ -o $@ 10 | 11 | clean: 12 | $(RM) $(OBJS) $(TARGET) 13 | -------------------------------------------------------------------------------- /src/abstract-factory/cpp/button.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "text.h" 3 | #include "button.h" 4 | 5 | void Button::SetText(Text *pText) 6 | { 7 | this->m_pText = pText; 8 | } 9 | 10 | Button::~Button() 11 | { 12 | delete m_pText; 13 | } 14 | 15 | WinButton::WinButton() 16 | { 17 | std::cout << "Constructor of WinButton" << std::endl; 18 | } 19 | 20 | WinButton::~WinButton() 21 | { 22 | std::cout << "Destructor of WinButton" << std::endl; 23 | } 24 | 25 | UnixButton::UnixButton() 26 | { 27 | std::cout << "Constructor of UnixButton" << std::endl; 28 | } 29 | 30 | UnixButton::~UnixButton() 31 | { 32 | std::cout << "Destructor of UnixButton" << std::endl; 33 | } 34 | -------------------------------------------------------------------------------- /src/abstract-factory/cpp/button.h: -------------------------------------------------------------------------------- 1 | #ifndef BUTTON_H 2 | #define BUTTON_H 3 | 4 | class Text; 5 | 6 | class Button 7 | { 8 | public: 9 | Button(){} 10 | virtual void SetText(Text *pText); 11 | virtual ~Button(); 12 | private: 13 | Text *m_pText; 14 | }; 15 | 16 | class WinButton : public Button 17 | { 18 | public: 19 | WinButton(); 20 | virtual ~WinButton(); 21 | }; 22 | 23 | class UnixButton : public Button 24 | { 25 | public: 26 | UnixButton(); 27 | virtual ~UnixButton(); 28 | }; 29 | 30 | #endif//BUTTON_H 31 | -------------------------------------------------------------------------------- /src/abstract-factory/cpp/factory.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "text.h" 3 | #include "button.h" 4 | #include "factory.h" 5 | 6 | using namespace std; 7 | 8 | WinFactory::WinFactory() 9 | { 10 | cout << "Constructor of WinFactory" << endl; 11 | } 12 | 13 | WinFactory::~WinFactory() 14 | { 15 | cout << "Destructor of WinFactory" << endl; 16 | } 17 | 18 | UnixFactory::UnixFactory() 19 | { 20 | cout << "Constructor of UnixFactory" << endl; 21 | } 22 | 23 | UnixFactory::~UnixFactory() 24 | { 25 | cout << "Destructor of WinFactory" << endl; 26 | } 27 | 28 | Button* WinFactory::CreateButton() 29 | { 30 | return new WinButton(); 31 | } 32 | 33 | Text* WinFactory::CreateText() 34 | { 35 | return new WinText(); 36 | } 37 | 38 | Button* UnixFactory::CreateButton() 39 | { 40 | return new UnixButton(); 41 | } 42 | 43 | Text* UnixFactory::CreateText() 44 | { 45 | return new UnixText(); 46 | } 47 | -------------------------------------------------------------------------------- /src/abstract-factory/cpp/factory.h: -------------------------------------------------------------------------------- 1 | #ifndef FACTORY_H 2 | #define FACTORY_H 3 | 4 | class Text; 5 | class Button; 6 | 7 | class Factory 8 | { 9 | public: 10 | Factory(){} 11 | virtual Button* CreateButton() = 0; 12 | virtual Text* CreateText() = 0; 13 | virtual ~Factory(){} 14 | }; 15 | 16 | class WinFactory : public Factory 17 | { 18 | public: 19 | WinFactory(); 20 | Button* CreateButton(); 21 | Text* CreateText(); 22 | virtual ~WinFactory(); 23 | }; 24 | 25 | class UnixFactory : public Factory 26 | { 27 | public: 28 | UnixFactory(); 29 | Button* CreateButton(); 30 | Text* CreateText(); 31 | virtual ~UnixFactory(); 32 | }; 33 | 34 | #endif//FACTORY_H 35 | -------------------------------------------------------------------------------- /src/abstract-factory/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "text.h" 2 | #include "button.h" 3 | #include "factory.h" 4 | 5 | int main(void) { 6 | Factory *pWinFactory = new WinFactory(); 7 | Text *pWinText = pWinFactory->CreateText(); 8 | Button *pWinButton = pWinFactory->CreateButton(); 9 | pWinButton->SetText(pWinText); 10 | 11 | delete pWinButton; 12 | 13 | Factory *pUnixFactory = new UnixFactory(); 14 | Text *pUnixText = pUnixFactory->CreateText(); 15 | Button *pUnixButton = pUnixFactory->CreateButton(); 16 | pUnixButton->SetText(pUnixText); 17 | 18 | delete pUnixButton; 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/abstract-factory/cpp/text.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "text.h" 3 | 4 | Text::~Text() 5 | { 6 | std::cout << "Destruct a Text" << std::endl; 7 | } 8 | 9 | WinText::~WinText() 10 | { 11 | std::cout << "Destruct a WinText" << std::endl; 12 | } 13 | 14 | UnixText::~UnixText() 15 | { 16 | std::cout << "Destruct a UnixText" << std::endl; 17 | } 18 | -------------------------------------------------------------------------------- /src/abstract-factory/cpp/text.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXT_H 2 | #define TEXT_H 3 | 4 | class Text 5 | { 6 | public: 7 | Text(){} 8 | Text(const Text&) = delete; 9 | Text& operator=(const Text&) = delete; 10 | virtual ~Text(); 11 | }; 12 | 13 | class WinText : public Text 14 | { 15 | public: 16 | WinText(){} 17 | virtual ~WinText(); 18 | }; 19 | 20 | class UnixText : public Text 21 | { 22 | public: 23 | UnixText(){} 24 | virtual ~UnixText(); 25 | }; 26 | 27 | #endif//TEXT_H 28 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/Factory.pm: -------------------------------------------------------------------------------- 1 | package Factory; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = { 9 | name => $args->{name} || "anonymous", 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub name { 15 | my ($self, $name) = @_; 16 | $self->{name} = $name if defined $name; 17 | return $self->{name}; 18 | } 19 | 20 | sub createProductA { 21 | die "ABSTRACT CLASS METHOD CANNOT BE CALLED DIRECTLY\n"; 22 | } 23 | 24 | sub createProductB { 25 | die "ABSTRACT CLASS METHOD CANNOT BE CALLED DIRECTLY\n"; 26 | } 27 | 28 | 1; 29 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/Factory/FactoryA.pm: -------------------------------------------------------------------------------- 1 | package Factory::FactoryA; 2 | use parent Factory; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | use ProductA::ProductA1; 8 | use ProductB::ProductB1; 9 | 10 | sub new { 11 | my ($class, $args) = @_; 12 | return $class->SUPER::new($args); 13 | } 14 | 15 | sub createProductA { 16 | return ProductA::ProductA1->new({name => "FA_A#1"}); 17 | } 18 | 19 | sub createProductB { 20 | return ProductB::ProductB1->new({name => "FA_B#1"}); 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/Factory/FactoryB.pm: -------------------------------------------------------------------------------- 1 | package Factory::FactoryB; 2 | use parent Factory; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | use ProductA::ProductA2; 8 | use ProductB::ProductB2; 9 | 10 | sub new { 11 | my ($class, $args) = @_; 12 | return $class->SUPER::new($args); 13 | } 14 | 15 | sub createProductA { 16 | return ProductA::ProductA2->new({name => "FB_A#1"}); 17 | } 18 | 19 | sub createProductB { 20 | return ProductB::ProductB2->new({name => "FB_B#1"}); 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/Product.pm: -------------------------------------------------------------------------------- 1 | package Product; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = { 9 | name => $args->{name}, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub name { 15 | my ($self, $name) = @_; 16 | $self->{name} = $name if defined $name; 17 | return $self->{name}; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/ProductA.pm: -------------------------------------------------------------------------------- 1 | package ProductA; 2 | use parent Product; 3 | 4 | sub new { 5 | my ($class, $args) = @_; 6 | return $class->SUPER::new($args); 7 | } 8 | 9 | 1; 10 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/ProductA/ProductA1.pm: -------------------------------------------------------------------------------- 1 | package ProductA::ProductA1; 2 | use parent ProductA; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | return $class->SUPER::new($args); 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/ProductA/ProductA2.pm: -------------------------------------------------------------------------------- 1 | package ProductA::ProductA2; 2 | use parent ProductA; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | return $class->SUPER::new($args); 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/ProductB.pm: -------------------------------------------------------------------------------- 1 | package ProductB; 2 | use parent Product; 3 | 4 | sub new { 5 | my ($class, $args) = @_; 6 | return $class->SUPER::new($args); 7 | } 8 | 9 | 1; 10 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/ProductB/ProductB1.pm: -------------------------------------------------------------------------------- 1 | package ProductB::ProductB1; 2 | use parent ProductB; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | return $class->SUPER::new($args); 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/ProductB/ProductB2.pm: -------------------------------------------------------------------------------- 1 | package ProductB::ProductB2; 2 | use parent ProductB; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | return $class->SUPER::new($args); 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /src/abstract-factory/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Factory::FactoryA; 7 | use Factory::FactoryB; 8 | 9 | sub produce { 10 | my ($factory) = @_; 11 | my $pa = $factory->createProductA; 12 | my $pb = $factory->createProductB; 13 | print "factory ", $factory->name, " created two product: ", $pa->name, 14 | " ,", $pb->name, "\n"; 15 | } 16 | 17 | produce(Factory::FactoryA->new({name => "Factory A#1"})); 18 | produce(Factory::FactoryB->new({name => "Factory B#1"})); 19 | -------------------------------------------------------------------------------- /src/abstract-factory/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/abstract-factory/uml.png -------------------------------------------------------------------------------- /src/adapter/adapter.md: -------------------------------------------------------------------------------- 1 | #Adapt模式 2 | 3 | ##作用: 4 |    5 | 将一个类的接口转换成客户希望的另外一个接口。Adapt 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 6 | 7 | ##UML示意图 8 | 1. 采用继承原有接口类的方式 9 | ![采用继承原有接口类的方式](./uml1.png) 10 | 2. 采用组合原有接口类的方式 11 | ![采用组合原有接口类的方式](./uml2.png) 12 | 13 | ##解析: 14 | 15 | Adapt模式其实就是把完成同样的一个功能但是接口不能兼容的类桥接在一起使之可以在一起工作,这个模式使得复用旧的接口成为可能。 16 | 17 | ##实现: 18 | 19 | Adapt模式有两种实现办法,一种是采用继承原有接口类的方法,一种是采用组合原有接口类的方法,这里采用的是第二种实现方法。 20 | 21 | ##应用场景 22 | 23 | 在以下各种情况下使用适配器模式: 24 | 25 | 1. 系统需要使用现有的类,而此类的接口不符合系统的需要。 26 | 2. 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。 27 | 3. (对对象适配器而言)在设计里,需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。 -------------------------------------------------------------------------------- /src/adapter/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | adapter.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/adapter/cpp/adapter.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "adapter.h" 3 | 4 | void Adaptee::SpecialRequest() 5 | { 6 | std::cout << "SpecialRequest of Adaptee" << std::endl; 7 | } 8 | 9 | Adapter::Adapter(Adaptee *pAdaptee) 10 | : m_pAdaptee(pAdaptee) {} 11 | 12 | Adapter::~Adapter() 13 | { 14 | delete m_pAdaptee; 15 | m_pAdaptee = NULL; 16 | } 17 | 18 | void Adapter::Request() 19 | { 20 | std::cout << "Request of Adapter" << std::endl; 21 | m_pAdaptee->SpecialRequest(); 22 | } 23 | -------------------------------------------------------------------------------- /src/adapter/cpp/adapter.h: -------------------------------------------------------------------------------- 1 | #ifndef ADAPTER_H 2 | #define ADAPTER_H 3 | 4 | // 需要被Adapt的类 5 | class Target 6 | { 7 | public: 8 | Target(){} 9 | virtual ~Target(){} 10 | virtual void Request() = 0; 11 | }; 12 | 13 | // 与被Adapt对象提供不兼容接口的类 14 | class Adaptee 15 | { 16 | public: 17 | Adaptee(){} 18 | ~Adaptee(){} 19 | void SpecialRequest(); 20 | }; 21 | 22 | // 进行Adapt的类,采用聚合原有接口类的方式 23 | class Adapter : public Target 24 | { 25 | public: 26 | Adapter(Adaptee *pAdaptee); 27 | virtual ~Adapter(); 28 | virtual void Request(); 29 | private: 30 | Adaptee *m_pAdaptee; 31 | }; 32 | 33 | #endif//ADAPTER_H 34 | -------------------------------------------------------------------------------- /src/adapter/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "adapter.h" 2 | 3 | int main(void) { 4 | Adaptee *pAdaptee = new Adaptee(); 5 | Target *pTarget = new Adapter(pAdaptee); 6 | pTarget->Request(); 7 | 8 | delete pTarget; 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/adapter/perl/Adapter.pm: -------------------------------------------------------------------------------- 1 | package Adapter; 2 | 3 | use strict; 4 | use warnings; 5 | use Data::Dump; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = { 10 | subject => $args->{subject}, 11 | sound => $args->{sound}, 12 | }; 13 | return bless $self, $class; 14 | } 15 | 16 | sub name { 17 | my ($self, $name) = @_; 18 | $self->{subject}->{name} = $name if defined($name); 19 | return $self->{subject}->name; 20 | } 21 | 22 | sub sound { 23 | my ($self) = @_; 24 | my $sound = $self->{sound}; 25 | return $self->{subject}->$sound; 26 | } 27 | 28 | 1; 29 | -------------------------------------------------------------------------------- /src/adapter/perl/Animal.pm: -------------------------------------------------------------------------------- 1 | package Animal; 2 | 3 | use strict; 4 | use warnings; 5 | use Data::Dump; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = { 10 | name => $args->{name} || "anonymous", 11 | }; 12 | print "[WORLD]: An animal named ", $self->{name}, " was born\n"; 13 | return bless $self, $class; 14 | } 15 | 16 | sub DESTROY { 17 | my $self = shift; 18 | print "[WORLD]: ", $self->name, " dies\n"; 19 | } 20 | 21 | sub name { 22 | my ($self, $name) = @_; 23 | $self->{name} = $name if defined($name); 24 | return $self->{name}; 25 | } 26 | 27 | 1; 28 | -------------------------------------------------------------------------------- /src/adapter/perl/Animal/Cat.pm: -------------------------------------------------------------------------------- 1 | package Animal::Cat; 2 | our @ISA = qw/Animal/; 3 | 4 | sub new { 5 | my ($class, $args) = @_; 6 | my $self = $class->SUPER::new($args); 7 | return bless $self, $class; 8 | } 9 | 10 | sub meow { 11 | return "meow!"; 12 | } 13 | 14 | 1; 15 | -------------------------------------------------------------------------------- /src/adapter/perl/Animal/Dog.pm: -------------------------------------------------------------------------------- 1 | package Animal::Dog; 2 | #use parent Animal; 3 | use Animal; 4 | our @ISA = qw/Animal/; 5 | 6 | use strict; 7 | use warnings; 8 | use Data::Dump; 9 | 10 | sub new { 11 | my ($class, $args) = @_; 12 | my $self = $class->SUPER::new($args); 13 | return bless $self, $class; 14 | } 15 | 16 | sub bark { 17 | return "woof!"; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /src/adapter/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use Animal::Dog; 6 | use Animal::Cat; 7 | use Adapter; 8 | 9 | my $dog = Animal::Dog->new({ 10 | name => "puppy", 11 | }); 12 | my $cat = Animal::Cat->new({ 13 | name => "mimi", 14 | }); 15 | 16 | my @creatures; 17 | push @creatures, Adapter->new({ 18 | subject => $dog, 19 | sound => "bark", 20 | }); 21 | push @creatures, Adapter->new({ 22 | subject => $cat, 23 | sound => "meow", 24 | }); 25 | 26 | $creatures[0]->name("snoopy"); 27 | 28 | foreach (@creatures) { 29 | print $_->name, " sounds like ", $_->sound, "\n"; 30 | } 31 | -------------------------------------------------------------------------------- /src/adapter/php/adapter.php: -------------------------------------------------------------------------------- 1 | _adaptee = $adaptee; 21 | } 22 | 23 | /** 24 | * 委派调用Adaptee的request方法 25 | */ 26 | public function request() { 27 | $this->_adaptee->specificRequest(); 28 | } 29 | 30 | public function __destruct() { 31 | $this->_adaptee = null; 32 | } 33 | } 34 | 35 | class Client { 36 | public static function main() { 37 | $adaptee = new Adaptee(); 38 | $adapter = new Adapter($adaptee); 39 | $adapter->request(); 40 | $adaptee = null; 41 | $adapter = null; 42 | } 43 | } 44 | 45 | Client::main(); 46 | 47 | ?> 48 | -------------------------------------------------------------------------------- /src/adapter/php/test.php: -------------------------------------------------------------------------------- 1 | specificRequest(); 20 | } 21 | } 22 | 23 | class Client { 24 | public static function main() { 25 | $adapter = new Adapter(); 26 | $adapter->request(); 27 | $adapter = null; 28 | } 29 | } 30 | 31 | Client::main(); 32 | 33 | ?> 34 | -------------------------------------------------------------------------------- /src/adapter/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/adapter/uml1.png -------------------------------------------------------------------------------- /src/adapter/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/adapter/uml2.png -------------------------------------------------------------------------------- /src/bridge/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | bridge.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/bridge/cpp/bridge.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bridge.h" 3 | 4 | void ConcreteImplementorA::OperationImpl() 5 | { 6 | std::cout << "Implementation by ConcreteImplementorA" << std::endl; 7 | } 8 | 9 | void ConcreteImplementorB::OperationImpl() 10 | { 11 | std::cout << "Implementation by ConcreteImplementorB" << std::endl; 12 | } 13 | 14 | Abstraction::Abstraction(Implementor *pImplementor) 15 | : m_pImplementor(pImplementor){} 16 | 17 | Abstraction::~Abstraction() 18 | { 19 | delete m_pImplementor; 20 | m_pImplementor = NULL; 21 | } 22 | 23 | void Abstraction::Operation() 24 | { 25 | m_pImplementor->OperationImpl(); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/bridge/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "bridge.h" 2 | 3 | int main(void) { 4 | ConcreteImplementorA *pImplA = new ConcreteImplementorA(); 5 | Abstraction *pAbstraction1 = new Abstraction(pImplA); 6 | pAbstraction1->Operation(); 7 | ConcreteImplementorB *pImplB = new ConcreteImplementorB(); 8 | Abstraction *pAbstraction2 = new Abstraction(pImplB); 9 | pAbstraction2->Operation(); 10 | 11 | delete pAbstraction1; 12 | delete pAbstraction2; 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/bridge/perl/Abstraction.pm: -------------------------------------------------------------------------------- 1 | package Abstraction; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $imp) = @_; 8 | my $self = { 9 | imp => $imp, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub implementator { 15 | my ($self, $imp) = @_; 16 | $self->{imp} = $imp if defined $imp; 17 | return $self->{imp}; 18 | } 19 | 20 | sub operate { 21 | my $self = shift; 22 | $self->{imp}->operateImp; 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /src/bridge/perl/Abstraction/RefinedAbstraction.pm: -------------------------------------------------------------------------------- 1 | package Abstraction::RefinedAbstraction; 2 | use parent Abstraction; 3 | 4 | sub new { 5 | my ($class, $imp) = @_; 6 | my $self = $class->SUPER::new($imp); 7 | return $self; 8 | } 9 | 10 | sub operate { 11 | my $self = shift; 12 | print ref $self, " operate:\n"; 13 | $self->{imp}->operateImp; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /src/bridge/perl/Implementator.pm: -------------------------------------------------------------------------------- 1 | package Implementator; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = {}; 9 | return bless $self, $class; 10 | } 11 | 12 | sub operateImp { 13 | die "ABSTRACT CLASS METHOD CANNOT BE CALLED DIRECTLY\n"; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /src/bridge/perl/Implementator/ConcreteImplementatorA.pm: -------------------------------------------------------------------------------- 1 | package Implementator::ConcreteImplementatorA; 2 | use parent Implementator; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | return $self; 11 | } 12 | 13 | sub operateImp { 14 | my $self = shift; 15 | print ref $self, " operate Imp\n"; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /src/bridge/perl/Implementator/ConcreteImplementatorB.pm: -------------------------------------------------------------------------------- 1 | package Implementator::ConcreteImplementatorB; 2 | use parent Implementator; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | return $self; 11 | } 12 | 13 | sub operateImp { 14 | my $self = shift; 15 | print ref $self, " operate Imp\n"; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /src/bridge/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # auther: oxnz 3 | # coding: utf-8 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use Abstraction::RefinedAbstraction; 9 | use Implementator::ConcreteImplementatorA; 10 | use Implementator::ConcreteImplementatorB; 11 | 12 | my $abs = Abstraction::RefinedAbstraction->new( 13 | Implementator::ConcreteImplementatorA->new); 14 | $abs->operate; 15 | $abs = Abstraction::RefinedAbstraction->new( 16 | Implementator::ConcreteImplementatorB->new); 17 | $abs->operate; 18 | -------------------------------------------------------------------------------- /src/bridge/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/bridge/uml.png -------------------------------------------------------------------------------- /src/builder/builder.md: -------------------------------------------------------------------------------- 1 | #建造者(Builder)模式 2 | 3 | ##一. 概述 4 | 5 | Builder 模式要解决的问题是:当我们要创建的对象很复杂的时候(通常是由很多其他的对象组合而成),我们要要复杂对象的创建过程和这个对象的表示(展示)分离开来,这样做的好处就是通过一步步的进行复杂对象的构建,由于在每一步的构造过程中可以引入参数,使得经过相同的步骤创建最后得到的对象的展示不一样。 6 | 7 | ##二. 举例 8 | 9 | KFC 与 Mcdonalds 的汉堡生成过程大致都是一样的,假设分为4个步骤; 10 | 11 | 但是 KFC 与 Mcdonalds 的汉堡味道有所差别,主要是在每一步的细节上有所不同。 12 | 13 | 顾客要吃汉堡并不关心具体的生产步骤,其实汉堡店也不关心,因为数百年来,这些步骤者是相同的,差别只在细节上。比如盐放多少,辣椒放多少等等。 14 | 15 | 结构如下: 16 | ![uml图](./uml.png) 17 | 18 | >Builder:为最基本的生产步骤 19 | 20 | >KFCBuilder:为KFC的具体生产步骤 21 | 22 | >MCDBuilder:为Mcdonalds的具体生产步骤 23 | 24 | >Director:为指挥者,用它来控件建造过程 25 | 26 | ##三. 说明 27 | 28 | 1. 建造者模式,在建造顺序上通常是稳定的。 29 | 2. 指挥者(Director),来隔离用户与具体建造过程的关联。 30 | 31 | 3. 它的好处是,客户端不需要知道具体的建造者方法,也不用但心忘记某一步骤没写,这些步骤统一由Director来调用。 -------------------------------------------------------------------------------- /src/builder/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | builder.o \ 5 | director.o \ 6 | 7 | $(TARGET): $(OBJS) 8 | $(CXX) $^ -o $@ 9 | 10 | clean: 11 | $(RM) $(OBJS) $(TARGET) 12 | -------------------------------------------------------------------------------- /src/builder/cpp/builder.h: -------------------------------------------------------------------------------- 1 | #ifndef BUILDER_H 2 | #define BUILDER_H 3 | 4 | class Builder 5 | { 6 | public: 7 | virtual void BuildStep1() = 0; 8 | virtual void BuildStep2() = 0; 9 | virtual void BuildStep3() = 0; 10 | virtual void BuildStep4() = 0; 11 | virtual ~Builder(){} 12 | }; 13 | 14 | class KFCBuilder : public Builder 15 | { 16 | void BuildStep1(); 17 | void BuildStep2(); 18 | void BuildStep3(); 19 | void BuildStep4(); 20 | }; 21 | 22 | class MCDBuilder : public Builder 23 | { 24 | void BuildStep1(); 25 | void BuildStep2(); 26 | void BuildStep3(); 27 | void BuildStep4(); 28 | }; 29 | #endif//BUILDER_H 30 | -------------------------------------------------------------------------------- /src/builder/cpp/director.cc: -------------------------------------------------------------------------------- 1 | #include "builder.h" 2 | #include "director.h" 3 | 4 | Director::Director(Builder *builder) 5 | { 6 | m_pBuilder = builder; 7 | } 8 | 9 | void Director::Create() 10 | { 11 | m_pBuilder->BuildStep1(); 12 | m_pBuilder->BuildStep2(); 13 | m_pBuilder->BuildStep3(); 14 | m_pBuilder->BuildStep4(); 15 | } 16 | -------------------------------------------------------------------------------- /src/builder/cpp/director.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTOR_H 2 | #define DIRECTOR_H 3 | 4 | class Builder; 5 | 6 | class Director 7 | { 8 | private: 9 | Builder *m_pBuilder; 10 | public: 11 | Director(Builder *builder); 12 | void Create(); 13 | }; 14 | 15 | #endif//DIRECTOR_H 16 | -------------------------------------------------------------------------------- /src/builder/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "builder.h" 2 | #include "director.h" 3 | 4 | int main(void) { 5 | KFCBuilder kfc; 6 | Director director(&kfc); 7 | director.Create(); 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/builder/perl/Builder.pm: -------------------------------------------------------------------------------- 1 | package Builder; 2 | 3 | use strict; 4 | use warnings; 5 | use Product; 6 | 7 | sub new { 8 | return bless { 9 | product => Product->new, 10 | }, shift; 11 | } 12 | 13 | sub product { 14 | my ($self, $product) = @_; 15 | return $self->{product}; 16 | } 17 | 18 | sub buildPart1 { 19 | die "ABSTRACT METHOD CANNOT BE CALLED DIRECTLY\n"; 20 | } 21 | 22 | sub buildPart2 { 23 | die "ABSTRACT METHOD CANNOT BE CALLED DIRECTLY\n"; 24 | } 25 | 26 | 1; 27 | -------------------------------------------------------------------------------- /src/builder/perl/Builder/ConcreteBuilder.pm: -------------------------------------------------------------------------------- 1 | package Builder::ConcreteBuilder; 2 | use parent Builder; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my $class = shift; 9 | my $self = $class->SUPER::new; 10 | return $self; 11 | } 12 | 13 | sub buildPart1 { 14 | my $self = shift; 15 | $self->{product}->add("part1"); 16 | } 17 | 18 | sub buildPart2 { 19 | my $self = shift; 20 | $self->{product}->add("part2"); 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /src/builder/perl/Director.pm: -------------------------------------------------------------------------------- 1 | package Director; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $builder) = @_; 8 | return bless { 9 | builder => $builder, 10 | }, $class; 11 | } 12 | 13 | sub product { 14 | my $self = shift; 15 | $self->{builder}->buildPart1; 16 | $self->{builder}->buildPart2; 17 | return $self->{builder}->product; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /src/builder/perl/Product.pm: -------------------------------------------------------------------------------- 1 | package Product; 2 | 3 | use strict; 4 | use warnings; 5 | use Data::Dump; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = {}; 10 | $self->{parts} = []; 11 | return bless $self, $class; 12 | } 13 | 14 | sub add { 15 | my ($self, $part) = @_; 16 | push $self->{parts}, $part; 17 | } 18 | 19 | sub show { 20 | print "Product consists of:\n"; 21 | my $parts = shift->{parts}; 22 | foreach (@$parts) { 23 | print $_, "\n"; 24 | } 25 | } 26 | 27 | 1; 28 | -------------------------------------------------------------------------------- /src/builder/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Director; 7 | use Builder::ConcreteBuilder; 8 | 9 | my $director = Director->new(Builder::ConcreteBuilder->new); 10 | my $product = $director->product; 11 | $product->show; 12 | 13 | -------------------------------------------------------------------------------- /src/builder/ruby/address.rb: -------------------------------------------------------------------------------- 1 | class Address 2 | attr_accessor :street, :street2, :city, :state, :zip, :address_type 3 | 4 | def initialize(&block) 5 | #set default values 6 | self.city = "Chicago" 7 | self.state = "IL" 8 | #set values from block 9 | instance_eval &block if block_given? 10 | end 11 | end 12 | 13 | def testDefaultValues 14 | myaddress = Address.new 15 | assert_equal("Chicago", myaddress.city) 16 | assert_equal("IL", myaddress.state) 17 | end 18 | 19 | def testStreetStateZip 20 | myaddress = Address.new do 21 | self.street = "this is the street" 22 | self.zip = "11111" 23 | end 24 | assert_equal("Chicago", myaddress.city) 25 | assert_equal("IL", myaddress.state) 26 | assert_equal("this is the street", myaddress.street) 27 | assert_equal("11111", myaddress.zip) 28 | end 29 | 30 | testDefaultValues() 31 | -------------------------------------------------------------------------------- /src/builder/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/builder/uml.png -------------------------------------------------------------------------------- /src/chain-of-responsibility/cpp/handler.h: -------------------------------------------------------------------------------- 1 | #ifndef HANDLER_H 2 | #define HANDLER_H 3 | 4 | class Handler 5 | { 6 | public: 7 | virtual void HandleRequest(int request) = 0; 8 | void SetSuccessor(Handler* succ); 9 | Handler* GetSuccessor() const; 10 | virtual ~Handler(); 11 | protected: 12 | Handler(); 13 | private: 14 | Handler *m_pSuccessor; 15 | }; 16 | 17 | //具体处理类 A 18 | class ConcreteHandlerA : public Handler 19 | { 20 | public: 21 | void HandleRequest(int request); 22 | }; 23 | 24 | //具体处理类 B 25 | class ConcreteHandlerB : public Handler 26 | { 27 | public: 28 | void HandleRequest(int request); 29 | }; 30 | 31 | //具体处理类 C 32 | class ConcreteHandlerC : public Handler 33 | { 34 | public: 35 | void HandleRequest(int request); 36 | }; 37 | 38 | #endif//HANDLER_H 39 | -------------------------------------------------------------------------------- /src/chain-of-responsibility/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "handler.h" 2 | 3 | int main() { 4 | Handler *h1 = new ConcreteHandlerA(); 5 | Handler *h2 = new ConcreteHandlerB(); 6 | Handler *h3 = new ConcreteHandlerC(); 7 | 8 | //设置其上级 9 | h1->SetSuccessor(h2); 10 | h2->SetSuccessor(h3); 11 | 12 | h1->HandleRequest(300); 13 | h1->HandleRequest(600); 14 | h1->HandleRequest(1500); 15 | h1->HandleRequest(3000); 16 | 17 | delete h1; 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /src/chain-of-responsibility/cpp/makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | handler.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/chain-of-responsibility/perl/Handler.pm: -------------------------------------------------------------------------------- 1 | package Handler; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = { 9 | name => $args->{name} || "anonymous handler", 10 | successor => $args->{successor} || [ qw() ], 11 | }; 12 | return bless $self, $class; 13 | } 14 | 15 | sub name { 16 | my ($self, $name) = @_; 17 | $self->{name} = $name if defined($name); 18 | return $self->{name}; 19 | } 20 | 21 | sub successor { 22 | my ($self, $successor) = @_; 23 | $self->{successor} = $successor if defined($successor); 24 | return $self->{successor}; 25 | } 26 | 27 | sub handleRequest { 28 | my ($self, $request) = @_; 29 | print "abstract handler ", $self->name, 30 | " cannot handle request ", $request, "\n"; 31 | } 32 | 33 | 1; 34 | -------------------------------------------------------------------------------- /src/chain-of-responsibility/perl/Handler/ConcreteHandler1.pm: -------------------------------------------------------------------------------- 1 | package Handler::ConcreteHandler1; 2 | use parent Handler; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | return $self; 11 | } 12 | 13 | sub handleRequest { 14 | my ($self, $request) = @_; 15 | if ($request > 0 and $request <= 10) { 16 | print "handler ", $self->name, " is handling request ", $request, "\n"; 17 | } else { 18 | #print "passing request to successor ", $self->successor, "\n"; 19 | $self->successor->handleRequest($request); 20 | } 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /src/chain-of-responsibility/perl/Handler/ConcreteHandler2.pm: -------------------------------------------------------------------------------- 1 | package Handler::ConcreteHandler2; 2 | use parent Handler; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | return $self; 11 | } 12 | 13 | sub handleRequest { 14 | my ($self, $request) = @_; 15 | if ($request > 10 and $request <= 20) { 16 | print "handler ", $self->name, " is handling request ", $request, "\n"; 17 | } else { 18 | #print "passing request to successor ", $self->successor, "\n"; 19 | $self->successor->handleRequest($request); 20 | } 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /src/chain-of-responsibility/perl/Handler/ConcreteHandler3.pm: -------------------------------------------------------------------------------- 1 | package Handler::ConcreteHandler3; 2 | use parent Handler; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | return $self; 11 | } 12 | 13 | sub handleRequest { 14 | my ($self, $request) = @_; 15 | if ($request > 20 and $request <= 30) { 16 | print "handler ", $self->name, " is handling request ", $request, "\n"; 17 | } else { 18 | print "handler ", $self->name, 19 | " cannot handle request ", $request, "\n"; 20 | } 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /src/chain-of-responsibility/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use Data::Dump; 6 | use Handler::ConcreteHandler1; 7 | use Handler::ConcreteHandler2; 8 | use Handler::ConcreteHandler3; 9 | 10 | my $h1 = Handler::ConcreteHandler1->new({ 11 | name => "concrete handler 1", 12 | }); 13 | my $h2 = Handler::ConcreteHandler2->new({ 14 | name => "concrete handler 2", 15 | }); 16 | my $h3 = Handler::ConcreteHandler3->new({ 17 | name => "concrete handler 3", 18 | }); 19 | 20 | $h1->successor($h2); 21 | $h2->successor($h3); 22 | 23 | my @requests = qw(2 5 14 22 18 3 35 27 20); 24 | print "requests: "; 25 | dd @requests; 26 | foreach my $request (@requests) { 27 | $h1->handleRequest($request); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/chain-of-responsibility/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/chain-of-responsibility/uml1.png -------------------------------------------------------------------------------- /src/chain-of-responsibility/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/chain-of-responsibility/uml2.png -------------------------------------------------------------------------------- /src/command/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | command.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/command/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "command.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | //定义一个执行类 5 | Reciever* pRev = new Reciever(); 6 | 7 | Command* pCmd1 = new Read_Command(pRev); 8 | Command* pCmd2 = new Write_Command(pRev); 9 | 10 | Invoker inv;//管理所有命令 11 | inv.AddCmd(pCmd1); 12 | inv.AddCmd(pCmd2); 13 | inv.Notify();//通知执行类,执行 14 | inv.DelCmd(pCmd1); 15 | inv.Notify(); 16 | inv.DelCmd(pCmd2); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/command/perl/Command.pm: -------------------------------------------------------------------------------- 1 | package Command; 2 | 3 | sub new { 4 | my ($class, $args) = @_; 5 | my $self = {}; 6 | return bless $self, $class; 7 | } 8 | 9 | sub execute { 10 | die "INTERFACE COMMAND CANNOT BE CALLED DIRECTLY\n"; 11 | } 12 | 13 | 1; 14 | -------------------------------------------------------------------------------- /src/command/perl/Command/CopyCommand.pm: -------------------------------------------------------------------------------- 1 | package Command::CopyCommand; 2 | use parent Command; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $receiver) = @_; 9 | my $self = $class->SUPER::new; 10 | $self->{receiver} = $receiver; 11 | return $self; 12 | } 13 | 14 | sub execute { 15 | my $self = shift; 16 | $self->{receiver}->copy; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /src/command/perl/Command/MacroCommand.pm: -------------------------------------------------------------------------------- 1 | package Command::MacroCommand; 2 | use parent Command; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | return $class->SUPER::new($args); 10 | } 11 | 12 | sub add { 13 | die "INTERFACE COMMAND CANNOT BE CALLED DIRECTLY\n"; 14 | } 15 | 16 | sub remove { 17 | die "INTERFACE COMMAND CANNOT BE CALLED DIRECTLY\n"; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /src/command/perl/Command/MacroCommand/DemoMacroCommand.pm: -------------------------------------------------------------------------------- 1 | package Command::MacroCommand::DemoMacroCommand; 2 | use parent Command::MacroCommand; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | $self->{commands} = []; 11 | return $self; 12 | } 13 | 14 | sub add { 15 | my ($self, $command) = @_; 16 | push $self->{commands}, $command; 17 | } 18 | 19 | sub remove { 20 | my ($self, $command) = @_; 21 | my $commands = $self->{commands}; 22 | my $i = 0; 23 | for ($i = 0; $i < @$commands; ++$i) { 24 | last if $command == $commands->[$i]; 25 | } 26 | splice(@$commands, $i, 1) if $i != @$commands; 27 | } 28 | 29 | sub execute { 30 | my $self = shift; 31 | my $commands = $self->{commands}; 32 | foreach my $command (@$commands) { 33 | $command->execute; 34 | } 35 | } 36 | 37 | 1; 38 | -------------------------------------------------------------------------------- /src/command/perl/Command/PasteCommand.pm: -------------------------------------------------------------------------------- 1 | package Command::PasteCommand; 2 | use parent Command; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $receiver) = @_; 9 | my $self = $class->SUPER::new; 10 | $self->{receiver} = $receiver; 11 | return $self; 12 | } 13 | 14 | sub execute { 15 | my $self = shift; 16 | $self->{receiver}->paste; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /src/command/perl/Invoker.pm: -------------------------------------------------------------------------------- 1 | package Invoker; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $command) = @_; 8 | my $self = { 9 | command => $command, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub action { 15 | my $self = shift; 16 | $self->{command}->execute; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /src/command/perl/Receiver.pm: -------------------------------------------------------------------------------- 1 | package Receiver; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = { 9 | name => $args->{name}, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub name { 15 | my ($self, $name) = @_; 16 | $self->{name} = $name if defined $name; 17 | return $self->{name}; 18 | } 19 | 20 | sub copy { 21 | my $self = shift; 22 | print $self->name, " do copy action\n"; 23 | } 24 | 25 | sub paste { 26 | my $self = shift; 27 | print $self->name, " do paste action\n"; 28 | } 29 | 30 | 1; 31 | -------------------------------------------------------------------------------- /src/command/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # auther: oxnz 3 | # coding: utf-8 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use Receiver; 9 | use Invoker; 10 | use Command::MacroCommand::DemoMacroCommand; 11 | use Command::PasteCommand; 12 | use Command::CopyCommand; 13 | 14 | my $receiver = Receiver->new({name => 'phppan'}); 15 | my $pasteCmd = Command::PasteCommand->new($receiver); 16 | my $copyCmd = Command::CopyCommand->new($receiver); 17 | my $macroCmd = Command::MacroCommand::DemoMacroCommand->new; 18 | $macroCmd->add($copyCmd); 19 | $macroCmd->add($pasteCmd); 20 | my $invoker = Invoker->new($macroCmd); 21 | $invoker->action; 22 | $macroCmd->remove($copyCmd); 23 | $invoker = Invoker->new($macroCmd); 24 | $invoker->action; 25 | -------------------------------------------------------------------------------- /src/command/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/command/uml1.png -------------------------------------------------------------------------------- /src/command/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/command/uml2.png -------------------------------------------------------------------------------- /src/composite/composite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/composite/composite.png -------------------------------------------------------------------------------- /src/composite/composite2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/composite/composite2.png -------------------------------------------------------------------------------- /src/composite/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | composite.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/composite/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "composite.h" 2 | 3 | int main(void) { 4 | Leaf *pLeaf1 = new Leaf(); 5 | Leaf *pLeaf2 = new Leaf(); 6 | Composite *pComposite = new Composite(); 7 | pComposite->Add(pLeaf1); 8 | pComposite->Add(pLeaf2); 9 | pComposite->Operation(); 10 | pComposite->GetChild(2)->Operation(); 11 | 12 | delete pComposite; 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/composite/perl/Component.pm: -------------------------------------------------------------------------------- 1 | package Component; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = {}; 9 | return bless $self, $class; 10 | } 11 | 12 | sub getComposite { 13 | die "INTERFACE METHOD CANNOT BE CALLED DIRECTLY\n"; 14 | } 15 | 16 | sub operate { 17 | die "INTERFACE METHOD CANNOT BE CALLED DIRECTLY\n"; 18 | } 19 | 20 | sub add { 21 | die "INTERFACE METHOD CANNOT BE CALLED DIRECTLY\n"; 22 | } 23 | 24 | sub remove { 25 | die "INTERFACE METHOD CANNOT BE CALLED DIRECTLY\n"; 26 | } 27 | 28 | sub getChild { 29 | die "INTERFACE METHOD CANNOT BE CALLED DIRECTLY\n"; 30 | } 31 | 32 | 1; 33 | -------------------------------------------------------------------------------- /src/composite/perl/Component/Leaf.pm: -------------------------------------------------------------------------------- 1 | package Component::Leaf; 2 | use parent Component; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $name) = @_; 9 | my $self = $class->SUPER::new; 10 | $self->{name} = $name || "anonymous"; 11 | return $self; 12 | } 13 | 14 | sub name { 15 | my ($self, $name) = @_; 16 | $self->{name} = $name if defined $name; 17 | return $self->{name}; 18 | } 19 | 20 | sub operate { 21 | my $self = shift; 22 | print scalar((caller(0))[3]), " ", $self->name, "\n"; 23 | } 24 | 25 | sub getComposite { 26 | return undef; 27 | } 28 | 29 | sub add { 30 | my ($self, $component) = @_; 31 | return undef; 32 | } 33 | 34 | sub remove { 35 | my ($self, $component) = @_; 36 | return undef; 37 | } 38 | 39 | sub getChild { 40 | return undef; 41 | } 42 | 43 | 1; 44 | -------------------------------------------------------------------------------- /src/composite/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # auther: oxnz 3 | # coding: utf-8 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use Component::Composite; 9 | use Component::Leaf; 10 | 11 | my $leaf1 = Component::Leaf->new("first leaf"); 12 | my $leaf2 = Component::Leaf->new("second leaf"); 13 | my $composite = Component::Composite->new; 14 | $composite->add($leaf1); 15 | $composite->add($leaf2); 16 | $composite->operate; 17 | $composite->remove($leaf2); 18 | $composite->operate; 19 | $composite->remove($leaf1); 20 | -------------------------------------------------------------------------------- /src/composite/ruby/test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | class Part 4 | def initialize name 5 | @name = name 6 | end 7 | def weight 8 | 0 9 | end 10 | end 11 | 12 | class Hand < Part 13 | def initialize 14 | super("Hand") 15 | @children = [] 16 | 5.times {add_child Finger.new} 17 | end 18 | def weight # component object 19 | weight = 5 20 | @children.each { |c| weight += c.weight } 21 | weight 22 | end 23 | def add_child child 24 | @children << child 25 | end 26 | end 27 | 28 | class Finger < Part 29 | def initialize 30 | super("Finger") 31 | end 32 | 33 | def weight # Leaf object 34 | 1 35 | end 36 | end 37 | 38 | hand = Hand.new 39 | puts hand.weight 40 | -------------------------------------------------------------------------------- /src/composite/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/composite/uml.png -------------------------------------------------------------------------------- /src/decorator/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | decorator.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/decorator/cpp/decorator.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "decorator.h" 3 | 4 | Decorator::~Decorator() 5 | { 6 | delete m_pComponent; 7 | m_pComponent = NULL; 8 | } 9 | 10 | void ConcreteComponent::Operation() 11 | { 12 | std::cout << "Operation of ConcreteComponent" << std::endl; 13 | } 14 | 15 | void ConcreteDecorator::Operation() 16 | { 17 | m_pComponent->Operation(); 18 | AddedBehavior(); 19 | } 20 | 21 | void ConcreteDecorator::AddedBehavior() 22 | { 23 | std::cout << "AddedBehavior of ConcreteDecorator" << std::endl; 24 | } 25 | -------------------------------------------------------------------------------- /src/decorator/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "decorator.h" 2 | 3 | int main(void) { 4 | // 初始化一个Component对象 5 | Component *pComponent = new ConcreteComponent(); 6 | // 采用这个Component对象去初始化一个Decorator对象, 7 | //   // 这样就可以为这个Component对象动态添加职责 8 | Decorator *pDecorator = new ConcreteDecorator(pComponent); 9 | pDecorator->Operation(); 10 | delete pDecorator; 11 | 12 | return 0; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/decorator/decorator.md: -------------------------------------------------------------------------------- 1 | #Decorator 模式 2 | 3 | ##作用: 4 | 5 | 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。 6 | 7 | ##UML结构图: 8 | 9 | ![UML结构图](./uml.png) 10 | 11 | ##抽象基类: 12 | 13 | 1. Component:定义一个对象接口,可以为这个接口动态的添加职责。 14 | 2. Decorator:维持一个指向Component的指针,并且有一个和Component一致的接口函数。 15 |    16 | 17 | ##接口函数: 18 | 19 | Component::Operation:这个接口函数由Component声明,因此Component的派生类都需要实现,可以在这个接口函数的基础上给它动态添加职责。 20 | 21 | ##解析: 22 | 23 | Decorator的派生类可以为ConcreateComponent类的对象动态的添加职责,或者可以这么说:Decorator的派生类装饰ConcreateComponent类的对象。具体是这么实现的,首先初始化一个ConcreateComponent类的对象(被装饰者),采用这个对象去生成一个Decorator对象(装饰者),之后对Operation函数的调用则是对这个Decorator对象成员函数的多态调用。这里的实现要点是Decorator类和ConcreateComponent类都继承自Component,从而两者的接口函数是一致的;其次,Decorator维护了一个指向Component的指针,从而可以实现对Component::Operation函数的动态调用。 -------------------------------------------------------------------------------- /src/decorator/perl/AddStamp.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | package AddStamp; 3 | # 4 | #@author: 0xnz 5 | #@update: Sat Sep 28 13:10:24 CST 2013 6 | 7 | use strict; 8 | use warnings; 9 | 10 | sub TIEHANDLE { 11 | my $class = shift; 12 | my $handle = shift; 13 | return bless \$handle, $class; 14 | } 15 | 16 | sub PRINT { 17 | my $handle = shift; 18 | my $stamp = localtime(); 19 | 20 | print $handle "$stamp ", @_; 21 | } 22 | 23 | sub CLOSE { 24 | my $self = shift; 25 | close $self; 26 | } 27 | 28 | 1; 29 | -------------------------------------------------------------------------------- /src/decorator/perl/decorated.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #@author: 0xnz 3 | #@update: Sat Sep 28 13:15:59 CST 2013 4 | #@link: http://www.perl.com/pub/2003/06/13/design1.html 5 | 6 | use strict; 7 | use warnings; 8 | 9 | use AddStamp; 10 | 11 | open LOG, ">output.tmp" or die "Couldn't write output.tmp: $!\n"; 12 | # After opening the file for writing as usual, I use the built-in tie function 13 | # to bind the LOG handle to the AddStamp class under the name STAMPED_LOG. 14 | # After that, I refer exclusively to STAMPED_LOG. 15 | tie *STAMPED_LOG, "AddStamp", *LOG; 16 | 17 | while (<>) { 18 | print STAMPED_LOG; 19 | } 20 | 21 | close STAMPED_LOG; 22 | 23 | -------------------------------------------------------------------------------- /src/decorator/python/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | class Foo(object): 5 | def f1(self): 6 | print ("original f1") 7 | def f2(self, x): 8 | print ("original f2: %s") % x 9 | 10 | class DecoratedFoo(object): 11 | def __init__(self, decoratee): 12 | self._decoratee = decoratee 13 | def f1(self): 14 | print ("decorated f1") 15 | self._decoratee.f1() 16 | def __getattr__(self, name): 17 | return getattr(self._decoratee, name) 18 | 19 | if __name__ == '__main__': 20 | f = Foo() 21 | df = DecoratedFoo(f) 22 | df.f1() 23 | f.f2('x') 24 | df.f2('xyz') 25 | -------------------------------------------------------------------------------- /src/decorator/ruby/test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | class Coffee 4 | def cost 5 | 2 6 | end 7 | end 8 | 9 | module Milk 10 | def cost 11 | super + 0.4 12 | end 13 | end 14 | 15 | module Sugar 16 | def cost 17 | super + 0.2 18 | end 19 | end 20 | 21 | coffee = Coffee.new 22 | coffee.extend(Milk) 23 | coffee.extend(Sugar) 24 | p coffee.cost 25 | -------------------------------------------------------------------------------- /src/decorator/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/decorator/uml.png -------------------------------------------------------------------------------- /src/facade/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | 5 | $(TARGET): $(OBJS) 6 | $(CXX) $^ -o $@ 7 | 8 | clean: 9 | $(RM) $(OBJS) $(TARGET) 10 | -------------------------------------------------------------------------------- /src/facade/perl/FileSys.pm: -------------------------------------------------------------------------------- 1 | package FileSys; 2 | 3 | use strict; 4 | use warnings; 5 | use FileSys::AntiVirus; 6 | use FileSys::Zipper; 7 | use FileSys::Encryptor; 8 | 9 | sub new { 10 | my ($class, $args) = @_; 11 | my $self = { 12 | antiVirus => FileSys::AntiVirus->new, 13 | zipper => FileSys::Zipper->new, 14 | encryptor => FileSys::Encryptor->new, 15 | }; 16 | return bless $self, $class; 17 | } 18 | 19 | sub operate { 20 | my ($self) = @_; 21 | print "file sys operating ...\n"; 22 | $self->{antiVirus}->operate; 23 | $self->{zipper}->operate; 24 | $self->{encryptor}->operate; 25 | } 26 | 27 | sub DESTROY { 28 | print "destroy\n"; 29 | } 30 | 31 | 1; 32 | -------------------------------------------------------------------------------- /src/facade/perl/FileSys/AntiVirus.pm: -------------------------------------------------------------------------------- 1 | package FileSys::AntiVirus; 2 | use parent FileSys; 3 | 4 | sub new { 5 | my ($class, $args) = @_; 6 | my $self = {}; 7 | return bless $self, $class; 8 | } 9 | 10 | sub operate { 11 | my ($self) = @_; 12 | print "anti virus operating ...\n"; 13 | } 14 | 15 | 1; 16 | -------------------------------------------------------------------------------- /src/facade/perl/FileSys/Encryptor.pm: -------------------------------------------------------------------------------- 1 | package FileSys::Encryptor; 2 | use parent FileSys; 3 | 4 | sub new { 5 | my ($class, $args) = @_; 6 | my $self = {}; 7 | return bless $self, $class; 8 | } 9 | 10 | sub operate { 11 | my ($self) = @_; 12 | print "encryptor operating ...\n"; 13 | } 14 | 15 | 1; 16 | -------------------------------------------------------------------------------- /src/facade/perl/FileSys/Zipper.pm: -------------------------------------------------------------------------------- 1 | package FileSys::Zipper; 2 | use parent FileSys; 3 | 4 | sub new { 5 | my ($class, $args) = @_; 6 | my $self = {}; 7 | return bless $self, $class; 8 | } 9 | 10 | sub operate { 11 | my ($self) = @_; 12 | print "zipper operating ...\n"; 13 | } 14 | 15 | 1; 16 | -------------------------------------------------------------------------------- /src/facade/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use FileSys; 6 | 7 | my $fs = FileSys->new; 8 | $fs->operate; 9 | -------------------------------------------------------------------------------- /src/facade/python/test.py: -------------------------------------------------------------------------------- 1 | #coding: utf-8 2 | 3 | class KillVirus: 4 | def operation(self): 5 | print "killing virus" 6 | 7 | class ZipFile: 8 | def operation(self): 9 | print "zipping" 10 | 11 | class EncryptFile: 12 | def operation(self): 13 | print "encrypting" 14 | 15 | # Facade 16 | class Filesys: 17 | def __init__(self): 18 | self._kv = KillVirus() 19 | self._zf = ZipFile() 20 | self._ef = EncryptFile() 21 | 22 | def operation(self): 23 | """Wrapped all details in this function""" 24 | [i.operation() for i in (self._kv, self._zf, self._ef)] 25 | 26 | if __name__ == '__main__': 27 | fs = Filesys() 28 | fs.operation() 29 | -------------------------------------------------------------------------------- /src/facade/ruby/test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | class Shape 4 | def draw 5 | raise NotImplementedError.new 6 | end 7 | end 8 | 9 | class Rectangle < Shape 10 | def draw 11 | puts "Rectangle draw" 12 | end 13 | end 14 | 15 | class Square < Shape 16 | def draw 17 | puts "Square draw" 18 | end 19 | end 20 | 21 | class Circle < Shape 22 | def draw 23 | puts "Circle draw" 24 | end 25 | end 26 | 27 | class ShapeMaker 28 | attr_reader :circle, :rectangle, :square 29 | def initialize 30 | @circle = Circle.new 31 | @rectangle = Rectangle.new 32 | @square = Square.new 33 | end 34 | 35 | def drawCircle 36 | @circle.draw 37 | end 38 | def drawRectangle 39 | @rectangle.draw 40 | end 41 | def drawSquare 42 | @square.draw 43 | end 44 | end 45 | 46 | sm = ShapeMaker.new 47 | sm.drawCircle() 48 | sm.drawRectangle() 49 | sm.drawSquare() 50 | -------------------------------------------------------------------------------- /src/facade/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/facade/uml1.png -------------------------------------------------------------------------------- /src/facade/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/facade/uml2.png -------------------------------------------------------------------------------- /src/facade/uml3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/facade/uml3.png -------------------------------------------------------------------------------- /src/factory-method/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | nokia.o \ 5 | lumia920factory.o \ 6 | 7 | $(TARGET): $(OBJS) 8 | $(CXX) $^ -o $@ 9 | 10 | clean: 11 | $(RM) $(OBJS) $(TARGET) 12 | -------------------------------------------------------------------------------- /src/factory-method/cpp/factory.h: -------------------------------------------------------------------------------- 1 | #ifndef FACTORY_H 2 | #define FACTORY_H 3 | 4 | class Nokia; 5 | 6 | class Factory 7 | { 8 | public: 9 | Factory(){} 10 | virtual Nokia* CreateNokia() = 0; 11 | virtual ~Factory(){} 12 | }; 13 | 14 | #endif//FACTORY_H 15 | -------------------------------------------------------------------------------- /src/factory-method/cpp/lumia920factory.cc: -------------------------------------------------------------------------------- 1 | #include "nokia.h" 2 | #include "lumia920factory.h" 3 | 4 | Nokia* Lumia920Factory::CreateNokia() 5 | { 6 | return new Lumia920(); 7 | } 8 | -------------------------------------------------------------------------------- /src/factory-method/cpp/lumia920factory.h: -------------------------------------------------------------------------------- 1 | #ifndef LUMIA920FACTORY_H 2 | #define LUMIA920FACTORY_H 3 | 4 | #include "factory.h" 5 | 6 | class Nokia; 7 | 8 | class Lumia920Factory : public Factory 9 | { 10 | public: 11 | virtual Nokia* CreateNokia(); 12 | }; 13 | 14 | #endif//LUMIA920FACTORY_H 15 | -------------------------------------------------------------------------------- /src/factory-method/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "nokia.h" 2 | #include "lumia920factory.h" 3 | 4 | int main(void) { 5 | Factory* pFactory = new Lumia920Factory(); 6 | Nokia* pNokia = pFactory->CreateNokia(); 7 | pNokia->Call("12345680"); 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/factory-method/cpp/nokia.cc: -------------------------------------------------------------------------------- 1 | #include "nokia.h" 2 | 3 | void Nokia::Call(const std::string& phoneNumber) const 4 | { 5 | std::cout << "Using a NOKIA Calling " << phoneNumber << std::endl; 6 | } 7 | 8 | void Lumia920::Call(const std::string& phoneNumber) const 9 | { 10 | std::cout << "Using a Lumia 920 Calling " << phoneNumber << std::endl; 11 | } 12 | 13 | void Lumia1020::Call(const std::string& phoneNumber) const 14 | { 15 | std::cout << "Using a Lumia 1020 Calling " << phoneNumber << std::endl; 16 | } 17 | -------------------------------------------------------------------------------- /src/factory-method/cpp/nokia.h: -------------------------------------------------------------------------------- 1 | #ifndef NOKIA_H 2 | #define NOKIA_H 3 | 4 | #include 5 | 6 | class Nokia 7 | { 8 | public: 9 | virtual void Call(const std::string& phoneNumber) const; 10 | virtual ~Nokia(){} 11 | }; 12 | 13 | class Lumia920 : public Nokia 14 | { 15 | public: 16 | virtual void Call(const std::string& phoneNumber) const; 17 | }; 18 | 19 | class Lumia1020 : public Nokia 20 | { 21 | public: 22 | virtual void Call(const std::string& phoneNumber) const; 23 | }; 24 | 25 | #endif//NOKIA_H 26 | -------------------------------------------------------------------------------- /src/factory-method/factory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/factory-method/factory.png -------------------------------------------------------------------------------- /src/factory-method/perl/Factory.pm: -------------------------------------------------------------------------------- 1 | package Factory; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = {}; 9 | return bless $self, $class; 10 | } 11 | 12 | sub create { 13 | die "INTERFACE METHOD CREATE CANNOT BE CALLED DIRECTLY\n"; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /src/factory-method/perl/Factory/LumiaFactory.pm: -------------------------------------------------------------------------------- 1 | package Factory::LumiaFactory; 2 | use parent Factory; 3 | use Nokia::Lumia; 4 | 5 | use strict; 6 | use warnings; 7 | 8 | sub new { 9 | my ($class, $args) = @_; 10 | my $self = $class->SUPER::new($args); 11 | return $self; 12 | } 13 | 14 | sub create { 15 | return Nokia::Lumia->new; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /src/factory-method/perl/Nokia: -------------------------------------------------------------------------------- 1 | ../../simple-factory/perl/Nokia -------------------------------------------------------------------------------- /src/factory-method/perl/Nokia.pm: -------------------------------------------------------------------------------- 1 | ../../simple-factory/perl/Nokia.pm -------------------------------------------------------------------------------- /src/factory-method/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use Factory::LumiaFactory; 6 | 7 | my $factory = Factory::LumiaFactory->new; 8 | my $nokia = $factory->create; 9 | $nokia->call(911); 10 | -------------------------------------------------------------------------------- /src/factory-method/python/test.py: -------------------------------------------------------------------------------- 1 | #coding: utf-8 2 | 3 | class EnglishGetter: 4 | '''simple echoes the msg''' 5 | def get(self, msg): 6 | return unicode(msg) 7 | 8 | class JapaneseGetter: 9 | '''A simple localizer a la gettext''' 10 | 11 | def __init__(self): 12 | self.trans = dict(dog="犬", cat="猫") 13 | 14 | def get(self, msg): 15 | '''we'll punt if we don't have a traslation''' 16 | try: 17 | return unicode(self.trans[msg], "utf-8") 18 | except KeyError: 19 | return unicode(msg) 20 | 21 | def get_localizer(language="English"): 22 | '''The factory method''' 23 | languages = dict(English=EnglishGetter, Japanese=JapaneseGetter) 24 | return languages[language]() 25 | 26 | # Create our localizers 27 | e, j = get_localizer('English'), get_localizer('Japanese') 28 | 29 | # Localize some text 30 | for msg in "dog parrot cat".split(): 31 | print e.get(msg), j.get(msg) 32 | -------------------------------------------------------------------------------- /src/factory-method/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/factory-method/uml1.png -------------------------------------------------------------------------------- /src/factory-method/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/factory-method/uml2.png -------------------------------------------------------------------------------- /src/flyweight/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | flyweight.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/flyweight/cpp/flyweight.h: -------------------------------------------------------------------------------- 1 | #ifndef FLYWEIGHT_H 2 | #define FLYWEIGHT_H 3 | 4 | #include 5 | #include 6 | 7 | class Flyweight 8 | { 9 | public: 10 | virtual void Operation(const std::string& extrinsicState){} 11 | std::string GetIntrinsicState(); 12 | virtual ~Flyweight(){} 13 | protected: 14 | Flyweight(std::string intrinsicState); 15 | private: 16 | std::string m_sIntrinsicState; 17 | }; 18 | 19 | class ConcreteFlyweight : public Flyweight 20 | { 21 | public: 22 | ConcreteFlyweight(std::string intrinsicState); 23 | void Operation(const std::string& extrinsicState); 24 | ~ConcreteFlyweight(){} 25 | }; 26 | 27 | class FlyweightFactory 28 | { 29 | public: 30 | FlyweightFactory(){} 31 | Flyweight* GetFlyweight(const std::string& key); 32 | ~FlyweightFactory(){} 33 | private: 34 | std::vector m_vFlyweight; 35 | }; 36 | 37 | #endif//FLYWEIGHT_H 38 | -------------------------------------------------------------------------------- /src/flyweight/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "flyweight.h" 2 | 3 | int main(void) { 4 | FlyweightFactory *fc = new FlyweightFactory(); 5 | //不同的对象,享元工厂将会创建新的享元类 6 | Flyweight *fw1 = fc->GetFlyweight("Object A"); 7 | Flyweight *fw2 = fc->GetFlyweight("Object B"); 8 | //相同的对象,享元工厂将会使用一个已创建的享元类 9 | Flyweight *fw3 = fc->GetFlyweight("Object A"); 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/flyweight/perl/Flyweight.pm: -------------------------------------------------------------------------------- 1 | package Flyweight; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $state) = @_; 8 | my $self = { 9 | state => $state, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub operate { 15 | die "ABSTRACT CLASS METHOD CANNOT BE CALLED DIRECTLY\n"; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /src/flyweight/perl/Flyweight/ConcreteFlyweight.pm: -------------------------------------------------------------------------------- 1 | package Flyweight::ConcreteFlyweight; 2 | use parent Flyweight; 3 | 4 | sub new { 5 | my ($class, $state) = @_; 6 | my $self = $class->SUPER::new($state); 7 | return $self; 8 | } 9 | 10 | sub operate { 11 | my ($self, $state) = @_; 12 | print scalar((caller(0))[3]), " intrinsic ", $self->{state}, " extrinsic ", 13 | $state, "\n"; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /src/flyweight/perl/Flyweight/UnsharedConcreteFlyweight.pm: -------------------------------------------------------------------------------- 1 | package Flyweight::UnsharedConcreteFlyweight; 2 | use parent Flyweight; 3 | 4 | sub new { 5 | my ($class, $args) = @_; 6 | my $self = $class->SUPER::new($args); 7 | $self{flyweights} = []; 8 | return bless $self; 9 | } 10 | 11 | sub add { 12 | my ($self, $f) = @_; 13 | my $fs = $self->{flyweights}; 14 | push @fs, $f; 15 | } 16 | 17 | sub operate { 18 | my ($self, $state) = @_; 19 | my $fs = $self->{flyweights}; 20 | foreach (@fs) { 21 | $_->operate($state); 22 | } 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /src/flyweight/perl/FlyweightFactory.pm: -------------------------------------------------------------------------------- 1 | package FlyweightFactory; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Flyweight::ConcreteFlyweight; 7 | use Flyweight::UnsharedConcreteFlyweight; 8 | 9 | sub new { 10 | my ($class, $args) = @_; 11 | my $self = { 12 | flyweights => {}, 13 | }; 14 | return bless $self, $class; 15 | } 16 | 17 | sub getFlyweight { 18 | my ($self, $state) = @_; 19 | if (ref $state eq "ARRAY") { 20 | my $uf = Flyweight::UnsharedConcreteFlyweight->new; 21 | foreach (@$state) { 22 | $uf->add($self->getFlyweight($_)); 23 | } 24 | return $uf; 25 | } else { 26 | my $fs = $self->{flyweights}; 27 | $fs->{$state} = Flyweight::ConcreteFlyweight->new($state) 28 | if not defined $fs->{$state}; 29 | return $fs->{$state}; 30 | } 31 | } 32 | 33 | 1; 34 | -------------------------------------------------------------------------------- /src/flyweight/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use FlyweightFactory; 7 | 8 | my $ff = FlyweightFactory->new; 9 | my $f = $ff->getFlyweight("state A"); 10 | $f->operate("state x"); 11 | $f = $ff->getFlyweight("state B"); 12 | $f->operate("state y"); 13 | $f = $ff->getFlyweight(["state A", "state B"]); 14 | $f->operate("state z"); 15 | -------------------------------------------------------------------------------- /src/flyweight/php/Readme.md: -------------------------------------------------------------------------------- 1 | #Flyweight Pattern In PHP 2 | 3 | 相对于其它模式,Flyweight模式在PHP的现有版本中没有太大的意义,因为PHP的生命周期 4 | 是页面级的,即从一个PHP文件执行开始会载入所需的资源,当执行完毕后,这些所有的资源 5 | 会被全部释放。而一般来说我们也不会让一个页面执行太长时间。 6 | -------------------------------------------------------------------------------- /src/flyweight/php/flyweight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/flyweight/php/flyweight.png -------------------------------------------------------------------------------- /src/flyweight/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/flyweight/uml.png -------------------------------------------------------------------------------- /src/interpreter/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | expression.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/interpreter/cpp/expression.cc: -------------------------------------------------------------------------------- 1 | #include "expression.h" 2 | 3 | TerminalExpression::TerminalExpression(const std::string& statement) 4 | { 5 | this->m_sStatement = statement; 6 | } 7 | 8 | void TerminalExpression::Interpret(const Context& c) 9 | { 10 | std::cout << this->m_sStatement << " Terminal Expression..." << std::endl; 11 | } 12 | 13 | NonterminalExpression::NonterminalExpression(const std::string& statement) 14 | { 15 | this->m_sStatement =statement; 16 | } 17 | 18 | void NonterminalExpression::Interpret(const Context& c) 19 | { 20 | std::cout << this->m_sStatement << " Noneterminal Expression..." << std::endl; 21 | } 22 | -------------------------------------------------------------------------------- /src/interpreter/cpp/expression.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPRESSION_H 2 | #define EXPRESSION_H 3 | 4 | #include 5 | 6 | class Context 7 | { 8 | public: 9 | Context(){} 10 | ~Context(){} 11 | }; 12 | 13 | class AbstractExpression 14 | { 15 | public: 16 | virtual void Interpret(const Context& c){} 17 | virtual ~AbstractExpression(){} 18 | protected: 19 | AbstractExpression(){} 20 | }; 21 | 22 | class TerminalExpression : public AbstractExpression 23 | { 24 | public: 25 | TerminalExpression(const std::string& statement); 26 | void Interpret(const Context& c); 27 | private: 28 | std::string m_sStatement; 29 | }; 30 | 31 | class NonterminalExpression : public AbstractExpression 32 | { 33 | public: 34 | NonterminalExpression(const std::string& statement); 35 | void Interpret(const Context& c); 36 | ~NonterminalExpression(){} 37 | 38 | private: 39 | std::string m_sStatement; 40 | }; 41 | 42 | #endif//EXPRESSION_H 43 | -------------------------------------------------------------------------------- /src/interpreter/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "expression.h" 3 | 4 | int main(int argc, char *argv[]) { 5 | Context* c = new Context(); 6 | 7 | std::list pList; 8 | pList.push_back(new TerminalExpression("FI")); 9 | pList.push_back(new NonterminalExpression("IF")); 10 | pList.push_back(new TerminalExpression("DONE")); 11 | pList.push_back(new NonterminalExpression("DO")); 12 | 13 | std::list::iterator it = pList.begin(); 14 | for(; it != pList.end(); ++it) { 15 | (*it)->Interpret(*c); 16 | } 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/interpreter/interpreter.md: -------------------------------------------------------------------------------- 1 | #解释器(Iterpreter)模式 2 | 3 | ##一. 解释器模式 4 | >定义:给定一个语言,定义它的文法的一种表示,并定一个解释器,这个解释器使用该表示来解释语言中的句子。 5 | 6 | 结构如下: 7 | ![结构](./uml.png) 8 | 9 | ##二. 说明 10 | 解释器模式就是用“迷你语言”来表现程序要解决的问题。 11 | 12 | 比如:在C语言解释器,当你输入 int 时,解释器就能正确的开辟一个 int 的空间出来。 13 | 14 | 再比如: linux 下常用的命令参数,如 ls -a,-a 就能被正确的解释成相应的命令。 15 | 16 | 优点:这种模式很容易改变和扩展文法,因为每个文法有一个文法类,也就是上面的表达式类。 17 | 18 | 缺点:当文法非常复杂时,要管理和维护很多个文法类。 -------------------------------------------------------------------------------- /src/interpreter/perl/Expression.pm: -------------------------------------------------------------------------------- 1 | package Expression; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | return bless {}, shift; 8 | } 9 | 10 | sub interpret { 11 | my ($self, $str) = @_; 12 | return $str; 13 | } 14 | 15 | 1; 16 | -------------------------------------------------------------------------------- /src/interpreter/perl/Expression/Char.pm: -------------------------------------------------------------------------------- 1 | package Expression::Char; 2 | use parent Expression; 3 | 4 | sub new { 5 | my $class = shift; 6 | return $class->SUPER::new; 7 | } 8 | 9 | sub interpret { 10 | my ($self, $str) = @_; 11 | return uc $str; 12 | } 13 | 14 | 1; 15 | -------------------------------------------------------------------------------- /src/interpreter/perl/Expression/Num.pm: -------------------------------------------------------------------------------- 1 | package Expression::Num; 2 | use parent Expression; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my $class = shift; 9 | return $class->SUPER::new; 10 | } 11 | 12 | sub interpret { 13 | my ($self, $i) = @_; 14 | my $itable = { 15 | 0 => "ZERO", 16 | 1 => "ONE", 17 | 2 => "TWO", 18 | 3 => "THREE", 19 | 4 => "FOUR", 20 | 5 => "FIVE", 21 | }; 22 | return $itable->{$i}; 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /src/interpreter/perl/Interpreter.pm: -------------------------------------------------------------------------------- 1 | package Interpreter; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Expression::Num; 7 | use Expression::Char; 8 | 9 | sub new { 10 | return bless {}, shift; 11 | } 12 | 13 | sub execute { 14 | my ($self, $str) = @_; 15 | foreach (split //, $str) { 16 | my $expr; 17 | if (m/^[0-9]$/) { 18 | $expr = Expression::Num->new; 19 | } else { 20 | $expr = Expression::Char->new; 21 | } 22 | print $expr->interpret($_), " "; 23 | } 24 | print "\n"; 25 | } 26 | 27 | 1; 28 | -------------------------------------------------------------------------------- /src/interpreter/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # auther: oxnz 3 | # coding: utf-8 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use Interpreter; 9 | 10 | my $interpreter = Interpreter->new; 11 | $interpreter->execute("12345abcde"); 12 | -------------------------------------------------------------------------------- /src/interpreter/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/interpreter/uml.png -------------------------------------------------------------------------------- /src/interpreter/uml_java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/interpreter/uml_java.png -------------------------------------------------------------------------------- /src/iterator/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | 5 | $(TARGET): $(OBJS) 6 | $(CXX) $^ -o $@ 7 | 8 | clean: 9 | $(RM) $(OBJS) $(TARGET) 10 | -------------------------------------------------------------------------------- /src/iterator/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // function called for each element 7 | void print(int elm) 8 | { 9 | cout << elm << ' '; 10 | } 11 | 12 | int main(int argc, char *argv[]) { 13 | vector coll; 14 | for (int i = 0; i < 10; ++i) 15 | coll.push_back(i); 16 | 17 | for_each(coll.begin(), coll.end(), print); 18 | cout << endl; 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/iterator/iterator.md: -------------------------------------------------------------------------------- 1 | #迭代器(Iterator)模式 2 | 3 | ##一. 举例说明 4 | 5 | 我们知道,在 STL 里提供 Iterator 来遍历 Vector 或者 List 数据结构。 6 | 7 | Iterator 模式也正是用来解决对一个聚合对象的遍历问题,将对聚合的遍历封装到一个类中进行,这样就避免暴露这个聚合对象的内部表示的可能。 8 | 9 | 例如在 STL 里有如相下结构: 10 | ![结构](./uml1.png) 11 | 12 | ##二. 迭代器模式 13 | 14 | 定义:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。 15 | ![迭代器模式](./uml2.png) 16 | 17 | 比较经典的例子是 STL 里的 for_each 操作: -------------------------------------------------------------------------------- /src/iterator/python/test.py: -------------------------------------------------------------------------------- 1 | #coding: utf-8 2 | '''Implementation of the iterator pattern with a generator 3 | 4 | http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/ 5 | ''' 6 | 7 | def count_to(count): 8 | '''Counts by work numbers, up to a maximum of five''' 9 | numbers = ["one", "two", "three", "four", "five"] 10 | # The zip keeps from counting over the limit 11 | for number, pos in zip(numbers, range(count)): 12 | '''yield可以用来为一个函数返回值塞数据''' 13 | yield number 14 | 15 | # Test the generator 16 | count_to_two = lambda : count_to(2) 17 | count_to_five = lambda : count_to(5) 18 | 19 | print 'Counting to two...' 20 | for number in count_to_two(): 21 | print number, 22 | print '\nCounting to five...' 23 | for number in count_to_five(): 24 | print number, 25 | print 26 | -------------------------------------------------------------------------------- /src/iterator/ruby/test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | list = ["Java", "c++", "ruby", "python"] 4 | list.each do |language| 5 | puts "Language: #{language}" 6 | end 7 | -------------------------------------------------------------------------------- /src/iterator/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/iterator/uml1.png -------------------------------------------------------------------------------- /src/iterator/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/iterator/uml2.png -------------------------------------------------------------------------------- /src/java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.errpro 8 | design-patterns 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | 14 | org.codehaus.mojo.groovy.runtime 15 | groovy-runtime-1.1 16 | 1.0-beta-3 17 | test 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/ConcreteFactory1.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public class ConcreteFactory1 extends Factory1 { 4 | public ProductA getProductA1() { 5 | return new ProductA1(); 6 | } 7 | public ProductB getProductB1() { 8 | return new ProductB1(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/ConcreteFactory2.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public class ConcreteFactory2 extends Factory2 { 4 | public ProductA getProductA2() { 5 | return new ProductA2(); 6 | } 7 | public ProductB getProductB2() { 8 | return new ProductB2(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/Factory1.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public abstract class Factory1 { 4 | abstract ProductA getProductA1(); 5 | abstract ProductB getProductB1(); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/Factory2.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | abstract class Factory2 { 4 | abstract ProductA getProductA2(); 5 | abstract ProductB getProductB2(); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/ProductA.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public interface ProductA { 4 | public void echo(); 5 | } 6 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/ProductA1.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public class ProductA1 implements ProductA { 4 | public void echo() { 5 | System.out.println("Factory 1 Product A"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/ProductA2.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public class ProductA2 implements ProductA { 4 | public void echo() { 5 | System.out.println("Factory 2 Product A"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/ProductB.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public interface ProductB { 4 | public void echo(); 5 | } 6 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/ProductB1.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public class ProductB1 implements ProductB { 4 | public void echo() { 5 | System.out.println("Factory 1 Product B"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/ProductB2.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public class ProductB2 implements ProductB { 4 | public void echo() { 5 | System.out.println("Factory 2 Product B"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/abstract_factory/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.abstract_factory; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | Factory1 f1 = new ConcreteFactory1(); 6 | ProductA pa1 = f1.getProductA1(); 7 | ProductB pb1 = f1.getProductB1(); 8 | 9 | pa1.echo(); 10 | pb1.echo(); 11 | 12 | Factory2 f2 = new ConcreteFactory2(); 13 | ProductA pa2 = f2.getProductA2(); 14 | ProductB pb2 = f2.getProductB2(); 15 | 16 | pa2.echo(); 17 | pb2.echo(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/adapter/Adaptee.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.adapter; 2 | 3 | public class Adaptee { 4 | public void specificRequest() { 5 | System.out.println("Original Interface"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/adapter/Adapter.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.adapter; 2 | 3 | // 1)对象适配器 4 | public class Adapter implements Target { 5 | private Adaptee adaptee = null; 6 | 7 | public Adapter(Adaptee adaptee) { 8 | this.adaptee = adaptee; 9 | } 10 | 11 | public void request() { 12 | adaptee.specificRequest(); 13 | } 14 | } 15 | 16 | 17 | // 2)类适配器 18 | /* 19 | public class Adapter extends Adaptee implements Target { 20 | public void request() { 21 | super.specificRequest(); 22 | } 23 | } 24 | */ 25 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/adapter/Target.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.adapter; 2 | 3 | public interface Target { 4 | public void request(); 5 | } 6 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/adapter/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.adapter; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | Adapter adapter = new Adapter(new Adaptee()); 6 | adapter.request(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/bridge/Abstraction.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.bridge; 2 | 3 | public class Abstraction { 4 | // Fields 5 | protected Implementor implementor; 6 | 7 | public void setImplementor(Implementor implementor) { 8 | this.implementor = implementor; 9 | } 10 | 11 | // Methods 12 | public void operation() { 13 | implementor.operation(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/bridge/ConcreteImplementorA.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.bridge; 2 | 3 | public class ConcreteImplementorA extends Implementor { 4 | @Override 5 | public void operation() { 6 | System.out.println("ConcreteImplementor A operation"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/bridge/ConcreteImplementorB.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.bridge; 2 | 3 | public class ConcreteImplementorB extends Implementor { 4 | @Override 5 | public void operation() { 6 | System.out.println("ConcreteImplementor B operation"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/bridge/Implementor.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.bridge; 2 | 3 | public abstract class Implementor { 4 | // Methods 5 | public abstract void operation(); 6 | } 7 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/bridge/RefinedAbstraction.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.bridge; 2 | 3 | public class RefinedAbstraction extends Abstraction { 4 | @Override 5 | public void operation() { 6 | implementor.operation(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/bridge/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.bridge; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | Abstraction abstraction = new RefinedAbstraction(); 6 | 7 | // Set implementation and call 8 | abstraction.setImplementor(new ConcreteImplementorA()); 9 | abstraction.operation(); 10 | 11 | // Change implementation and call 12 | abstraction.setImplementor(new ConcreteImplementorB()); 13 | abstraction.operation(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/builder/AbstractBuilder.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.builder; 2 | 3 | public interface AbstractBuilder { 4 | public void buildStep1(); 5 | 6 | public void buildStep2(); 7 | 8 | public void buildProduct(); 9 | } 10 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/builder/Director.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.builder; 2 | 3 | public class Director { 4 | private AbstractBuilder MCDBuilder = new MCDBuilder(); 5 | private AbstractBuilder KFCBuilder = new KFCBuilder(); 6 | 7 | public void buildMCD() { 8 | MCDBuilder.buildProduct(); 9 | } 10 | 11 | public void buildKFC() { 12 | KFCBuilder.buildProduct(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/builder/KFCBuilder.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.builder; 2 | 3 | public class KFCBuilder implements AbstractBuilder { 4 | public void buildStep1() { 5 | System.out.println("KFC build step1"); 6 | } 7 | 8 | public void buildStep2() { 9 | System.out.println("KFC build step1"); 10 | } 11 | 12 | public void buildProduct() { 13 | buildStep1(); 14 | buildStep2(); 15 | System.out.println("KFC Product Finished"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/builder/MCDBuilder.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.builder; 2 | 3 | public class MCDBuilder implements AbstractBuilder { 4 | public void buildStep1() { 5 | System.out.println("MCD Step 1"); 6 | } 7 | 8 | public void buildStep2() { 9 | System.out.println("MCD Step 2"); 10 | } 11 | 12 | public void buildProduct() { 13 | buildStep1(); 14 | buildStep2(); 15 | System.out.println("MCD Product Finished"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/builder/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.builder; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | System.out.println("Client want a MCD Product"); 6 | Director director = new Director(); 7 | director.buildMCD(); 8 | System.out.println("Client want a KFC Product"); 9 | director.buildKFC(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/chain_of_responsibility/AbstractRequest.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.chain_of_responsibility; 2 | 3 | public abstract class AbstractRequest { 4 | private String content = null; 5 | 6 | public AbstractRequest(String content) { 7 | this.content = content; 8 | } 9 | 10 | public String getContent() { 11 | return this.content; 12 | } 13 | 14 | public abstract int getRequestLevel(); 15 | } 16 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/chain_of_responsibility/Handler01.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.chain_of_responsibility; 2 | 3 | public class Handler01 extends AbstractHandler { 4 | @Override 5 | protected int getHandlerLevel() { 6 | return Levels.LEVEL_01; 7 | } 8 | 9 | @Override 10 | protected void handle(AbstractRequest request) { 11 | System.out.println("Handler-01 handling " + request.getContent()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/chain_of_responsibility/Handler02.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.chain_of_responsibility; 2 | 3 | public class Handler02 extends AbstractHandler { 4 | @Override 5 | protected int getHandlerLevel() { 6 | return Levels.LEVEL_02; 7 | } 8 | 9 | @Override 10 | protected void handle(AbstractRequest request) { 11 | System.out.println("Handler-02 handling " + request.getContent()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/chain_of_responsibility/Handler03.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.chain_of_responsibility; 2 | 3 | public class Handler03 extends AbstractHandler { 4 | @Override 5 | protected int getHandlerLevel() { 6 | return Levels.LEVEL_03; 7 | } 8 | 9 | @Override 10 | protected void handle(AbstractRequest request) { 11 | System.out.println("Handler-03 handling " + request.getContent()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/chain_of_responsibility/Levels.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.chain_of_responsibility; 2 | 3 | public interface Levels { 4 | public static final int LEVEL_01 = 1; 5 | public static final int LEVEL_02 = 2; 6 | public static final int LEVEL_03 = 3; 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/chain_of_responsibility/Request01.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.chain_of_responsibility; 2 | 3 | public class Request01 extends AbstractRequest { 4 | public Request01(String content) { 5 | super(content); 6 | } 7 | 8 | @Override 9 | public int getRequestLevel() { 10 | return Levels.LEVEL_01; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/chain_of_responsibility/Request02.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.chain_of_responsibility; 2 | 3 | public class Request02 extends AbstractRequest { 4 | public Request02(String content) { 5 | super(content); 6 | } 7 | 8 | @Override 9 | public int getRequestLevel() { 10 | return Levels.LEVEL_02; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/chain_of_responsibility/Request03.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.chain_of_responsibility; 2 | 3 | public class Request03 extends AbstractRequest { 4 | public Request03(String content) { 5 | super(content); 6 | } 7 | 8 | @Override 9 | public int getRequestLevel() { 10 | return Levels.LEVEL_03; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/chain_of_responsibility/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.chain_of_responsibility; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | // 创建指责链的所有节点 6 | AbstractHandler h01 = new Handler01(); 7 | AbstractHandler h02 = new Handler02(); 8 | AbstractHandler h03 = new Handler03(); 9 | 10 | // 进行链的组装,即头尾相连,一层套一层 11 | h01.setSuccessor(h02); 12 | h02.setSuccessor(h03); 13 | 14 | // 创建请求并提交到指责链中进行处理 15 | AbstractRequest r01 = new Request01("Request 01"); 16 | AbstractRequest r02 = new Request02("Request 02"); 17 | AbstractRequest r03 = new Request03("Request 03"); 18 | 19 | // 每次提交都是从链头开始遍历 20 | h01.handleRequest(r01); 21 | h01.handleRequest(r02); 22 | h01.handleRequest(r03); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/command/Command.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.command; 2 | 3 | public interface Command { 4 | public void execute(); 5 | } 6 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/command/CommandChange.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.command; 2 | 3 | public class CommandChange implements Command { 4 | private TV tv; 5 | private int channel; 6 | 7 | public CommandChange(TV tv, int channel) { 8 | this.tv = tv; 9 | this.channel = channel; 10 | } 11 | 12 | public void execute() { 13 | tv.changeChannel(channel); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/command/CommandOff.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.command; 2 | 3 | public class CommandOff implements Command { 4 | private TV tv; 5 | 6 | public CommandOff(TV tv) { 7 | this.tv = tv; 8 | } 9 | 10 | public void execute() { 11 | tv.turnOff(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/command/CommandOn.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.command; 2 | 3 | public class CommandOn implements Command { 4 | private TV tv; 5 | 6 | public CommandOn(TV tv) { 7 | this.tv = tv; 8 | } 9 | 10 | public void execute() { 11 | tv.turnOn(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/command/ConcreteCommand.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.command; 2 | 3 | public class ConcreteCommand implements Command { 4 | private Receiver receiver = null; 5 | private String state; 6 | 7 | public ConcreteCommand(Receiver receiver) { 8 | this.receiver = receiver; 9 | } 10 | 11 | public void execute() { 12 | receiver.action(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/command/Control.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.command; 2 | 3 | //可以看作是遥控器吧 4 | public class Control { 5 | private Command onCommand, offCommand, changeChannel; 6 | 7 | public Control(Command on, Command off, Command changeChannel) { 8 | this.onCommand = on; 9 | this.offCommand = off; 10 | this.changeChannel = changeChannel; 11 | } 12 | 13 | public void turnOn() { 14 | onCommand.execute(); 15 | } 16 | 17 | public void turnOff() { 18 | offCommand.execute(); 19 | } 20 | 21 | public void changeChannel() { 22 | changeChannel.execute(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/command/Invoker.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.command; 2 | 3 | public class Invoker { 4 | private Command command = null; 5 | 6 | public void setCommand(Command command) { 7 | System.out.println("Invoker: setCommand"); 8 | this.command = command; 9 | } 10 | 11 | public void runCommand() { 12 | command.execute(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/command/Receiver.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.command; 2 | 3 | public class Receiver { 4 | public void action() { 5 | System.out.println("Action in Receiver"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/command/TV.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.command; 2 | 3 | public class TV { 4 | public int currentChannel = 0; 5 | 6 | public void turnOn() { 7 | System.out.println("TV on"); 8 | } 9 | 10 | public void turnOff() { 11 | System.out.println("TV off"); 12 | } 13 | 14 | public void changeChannel(int channel) { 15 | this.currentChannel = channel; 16 | System.out.println("TV channel: " + channel); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/composite/Employee.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.composite; 2 | 3 | public interface Employee { 4 | public void add(Employee emp); 5 | 6 | public void remove(Employee emp); 7 | 8 | public Employee getEmployee(int index); 9 | 10 | public String getName(); 11 | 12 | public double getSalary(); 13 | 14 | public void echo(); 15 | } 16 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/composite/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.composite; 2 | 3 | /* 4 | * Manager(Composite) 5 | * Developer(Leaf) 6 | * Employee(Component) 7 | */ 8 | 9 | public class Test { 10 | public static void main(String[] args) { 11 | Employee emp1 = new Developer("John", 10000); 12 | Employee emp2 = new Developer("David", 14000); 13 | Employee manager1 = new Manager("Michael", 20000); 14 | manager1.add(emp1); 15 | manager1.add(emp2); 16 | Employee emp3 = new Developer("Daniel", 20000); 17 | Manager generalManager = new Manager("Mark", 50000); 18 | generalManager.add(emp3); 19 | generalManager.add(manager1); 20 | generalManager.echo(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/decorator/Component.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.decorator; 2 | 3 | //业务接口Component 4 | public interface Component { 5 | public void operation(); 6 | } 7 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/decorator/ConcreteComponent.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.decorator; 2 | 3 | public class ConcreteComponent implements Component { 4 | public void operation() { 5 | System.out.println("ConcreteComponent operation()"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/decorator/ConcreteDecorator.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.decorator; 2 | 3 | public class ConcreteDecorator extends Decorator { 4 | public ConcreteDecorator(Component component) { 5 | super(component); 6 | } 7 | 8 | public void operation() { 9 | super.operation(); 10 | extraBehavior(); 11 | } 12 | 13 | private void extraBehavior() { 14 | System.out.println("Extra Behavior"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/decorator/Decorator.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.decorator; 2 | 3 | //Decorator 4 | public class Decorator implements Component { 5 | private Component component; 6 | 7 | public Decorator(Component component) { 8 | this.component = component; 9 | } 10 | 11 | public void operation() { 12 | component.operation(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/decorator/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.decorator; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | ConcreteDecorator concreteDecorator = new ConcreteDecorator(new 6 | ConcreteComponent()); 7 | concreteDecorator.operation(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/facade/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.facade; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | OperatorWrapper opt = new OperatorWrapper(); 6 | opt.methodA(); 7 | opt.methodB(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/factory_method/ConcreteCreator1.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.factory_method; 2 | 3 | public class ConcreteCreator1 implements Creator { 4 | public Product factory() { 5 | return new ConcreteProductA(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/factory_method/ConcreteCreator2.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.factory_method; 2 | 3 | public class ConcreteCreator2 implements Creator { 4 | public Product factory() { 5 | return new ConcreteProductB(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/factory_method/ConcreteProductA.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.factory_method; 2 | 3 | public class ConcreteProductA implements Product { 4 | public ConcreteProductA() { 5 | System.out.println("ConcreteProduct A is contructed"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/factory_method/ConcreteProductB.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.factory_method; 2 | 3 | public class ConcreteProductB implements Product { 4 | public ConcreteProductB() { 5 | System.out.println("ConcreteProduct B is contructed"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/factory_method/Creator.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.factory_method; 2 | 3 | public interface Creator { 4 | public Product factory(); 5 | } 6 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/factory_method/Product.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.factory_method; 2 | 3 | public interface Product { 4 | } 5 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/factory_method/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.factory_method; 2 | 3 | public class Test { 4 | private static Creator c1, c2; 5 | private static Product pA, pB; 6 | 7 | public static void main(String[] args) { 8 | c1 = new ConcreteCreator1(); 9 | pA = c1.factory(); 10 | System.out.println("------------------"); 11 | c2 = new ConcreteCreator2(); 12 | pB = c2.factory(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/flyweight/ConcreteFont.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.flyweight; 2 | 3 | public class ConcreteFont implements Font { 4 | private String color; 5 | private int size; 6 | private FontInner fontInner; 7 | 8 | public ConcreteFont(FontInner fi) { 9 | this.fontInner = fi; 10 | } 11 | 12 | public void setFont(String color, int size) { 13 | this.color = color; 14 | this.size = size; 15 | } 16 | 17 | public void getFont() { 18 | System.out.println("String :" + this.fontInner.getFontString() + 19 | "--- color is: " + this.color + "--- size is:" + 20 | this.size); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/flyweight/Font.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.flyweight; 2 | 3 | public interface Font { 4 | public void setFont(String color, int size); 5 | 6 | public void getFont(); 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/flyweight/FontInner.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.flyweight; 2 | 3 | public class FontInner { 4 | private String fontString; 5 | private String status; 6 | 7 | public FontInner(String fontString, String status) { 8 | this.setFontString(fontString); 9 | this.setStatus(status); 10 | } 11 | 12 | public String getStatus() { 13 | return this.status; 14 | } 15 | 16 | public void setStatus(String status) { 17 | this.status = status; 18 | } 19 | 20 | public String getFontString() { 21 | return this.fontString; 22 | } 23 | 24 | public void setFontString(String fontString) { 25 | this.fontString = fontString; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/flyweight/FontInnerFactory.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.flyweight; 2 | 3 | import java.util.Hashtable; 4 | 5 | public class FontInnerFactory { 6 | private Hashtable charHashTable = new Hashtable(); 7 | 8 | public FontInnerFactory() { 9 | } 10 | 11 | public FontInner getFlyweight(String fontString, String status) { 12 | if (charHashTable.get(fontString) != null) { 13 | return charHashTable.get(fontString); 14 | } else { 15 | FontInner tmp = new FontInner(fontString, status); 16 | charHashTable.put(fontString, tmp); 17 | return tmp; 18 | } 19 | } 20 | 21 | public Hashtable getFactory() { 22 | return charHashTable; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/interpreter/AddExpression.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.interpreter; 2 | 3 | import java.util.HashMap; 4 | 5 | public class AddExpression extends SymbolExpression { 6 | public AddExpression(Expression left, Expression right) { 7 | super(left, right); 8 | } 9 | 10 | // 把左右两个表达式运算的结果加起来 11 | public int interprete(HashMap var) { 12 | return super.left.interprete(var) + super.right.interprete(var); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/interpreter/Client.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.interpreter; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Client { 6 | public static void main(String[] args) { 7 | HashMap ctx = new HashMap(); 8 | ctx.put("a", 10); 9 | ctx.put("b", 20); 10 | ctx.put("c", 30); 11 | ctx.put("d", 40); 12 | ctx.put("e", 50); 13 | ctx.put("f", 60); 14 | Calculator calc = new Calculator("a+b-c"); 15 | System.out.println("Result of a+b-c: " + calc.calculate(ctx)); 16 | calc = new Calculator("d-a-b+c"); 17 | System.out.println("Result of d-a-b+c: " + calc.calculate(ctx)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/interpreter/Expression.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.interpreter; 2 | 3 | import java.util.HashMap; 4 | 5 | public interface Expression { 6 | public int interprete(HashMap var); 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/interpreter/SubExpression.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.interpreter; 2 | 3 | import java.util.HashMap; 4 | 5 | public class SubExpression extends SymbolExpression { 6 | public SubExpression(Expression left, Expression right) { 7 | super(left, right); 8 | } 9 | 10 | // 左右两个表达式相减 11 | public int interprete(HashMap var) { 12 | return super.left.interprete(var) - super.right.interprete(var); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/interpreter/SymbolExpression.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.interpreter; 2 | 3 | public abstract class SymbolExpression implements Expression { 4 | protected Expression left; 5 | protected Expression right; 6 | 7 | // 所有的解析公式都应只关心自己左右两个表达式的结果 8 | public SymbolExpression(Expression left, Expression right) { 9 | this.left = left; 10 | this.right = right; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/interpreter/VarExpression.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.interpreter; 2 | 3 | import java.util.HashMap; 4 | 5 | public class VarExpression implements Expression { 6 | private String key; 7 | 8 | public VarExpression(String key) { 9 | this.key = key; 10 | } 11 | 12 | public int interprete(HashMap var) { 13 | return (Integer) var.get(this.key); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/mediator/Colleague.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.mediator; 2 | 3 | public abstract class Colleague { 4 | protected Mediator mediator; 5 | 6 | public Colleague(Mediator m) { 7 | this.mediator = m; 8 | } 9 | 10 | public abstract void sendMsg(String msg); 11 | 12 | public abstract void readMsg(String msg); 13 | } 14 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/mediator/ConcreteColleague2.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.mediator; 2 | 3 | public class ConcreteColleague2 extends Colleague { 4 | public ConcreteColleague2(Mediator m) { 5 | super(m); 6 | } 7 | 8 | public void sendMsg(String msg) { 9 | System.out.println("Colleague2 sends msg: " + msg); 10 | mediator.send(msg, this); 11 | } 12 | 13 | public void readMsg(String msg) { 14 | System.out.println("Colleague2 get msg: " + msg); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/mediator/ConcreteMediator.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.mediator; 2 | 3 | interface Mediator { 4 | public void send(String msg, Colleague c); 5 | } 6 | 7 | public class ConcreteMediator implements Mediator { 8 | private ConcreteColleague1 colleague1; 9 | private ConcreteColleague2 colleague2; 10 | 11 | public void setColleague1(ConcreteColleague1 colleague1) { 12 | this.colleague1 = colleague1; 13 | } 14 | 15 | public void setColleague2(ConcreteColleague2 colleague2) { 16 | this.colleague2 = colleague2; 17 | } 18 | 19 | public void send(String msg, Colleague c) { 20 | if (c == colleague1) { 21 | colleague2.readMsg(msg); 22 | } else { 23 | colleague1.readMsg(msg); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/mediator/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.mediator; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | ConcreteMediator mediator = new ConcreteMediator(); 6 | ConcreteColleague1 c1 = new ConcreteColleague1(mediator); 7 | ConcreteColleague2 c2 = new ConcreteColleague2(mediator); 8 | mediator.setColleague1(c1); 9 | mediator.setColleague2(c2); 10 | c1.sendMsg("吃了吗?"); 11 | c2.sendMsg("没有, 你要请客吗?"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/memento/RoleMemoManager.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.memento; 2 | 3 | public class RoleMemoManager { 4 | private RoleStateMemo memo; 5 | 6 | public RoleStateMemo getMemo() { 7 | return this.memo; 8 | } 9 | 10 | public void setMemo(RoleStateMemo memo) { 11 | this.memo = memo; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/memento/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.memento; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | GameRole role = new GameRole(); 6 | role.showState(); 7 | RoleMemoManager mm = new RoleMemoManager(); 8 | mm.setMemo(role.save()); 9 | role.fight(); // fight to death 10 | role.showState(); 11 | role.reload(mm.getMemo()); // refresh state to a previous state 12 | role.showState(); 13 | role.fight(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/observer/ConcreteObserver.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.observer; 2 | 3 | public class ConcreteObserver implements Observer { 4 | public void update() { 5 | System.out.println("update from ConcreteObserver"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/observer/Observer.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.observer; 2 | 3 | public interface Observer { 4 | void update(); 5 | } 6 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/observer/Subject.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.observer; 2 | 3 | public interface Subject { 4 | public void attach(Observer ob); 5 | 6 | public void detach(Observer ob); 7 | 8 | void notifyObservers(); 9 | 10 | public void change(); 11 | } 12 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/observer/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.observer; 2 | 3 | public class Test { 4 | public static void main(String args[]) { 5 | Observer ob1 = new ConcreteObserver(); 6 | Observer ob2 = new ConcreteObserver(); 7 | Subject sb = new ConcreteSubject(); 8 | 9 | sb.attach(ob1); 10 | sb.attach(ob2); 11 | 12 | sb.change(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/prototype/Prototype.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.prototype; 2 | 3 | public class Prototype implements Cloneable { 4 | private String name; 5 | 6 | public Prototype(String name) { 7 | this.name = name; 8 | } 9 | 10 | public String getName() { 11 | return this.name; 12 | } 13 | 14 | public void setName(String name) { 15 | this.name = name; 16 | } 17 | 18 | public Prototype clone() { 19 | Prototype p = null; 20 | try { 21 | p = (Prototype) super.clone(); 22 | } catch (CloneNotSupportedException e) { 23 | e.printStackTrace(); 24 | } 25 | return p; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/prototype/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.prototype; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | Prototype p = new Prototype("I am a prototype"); 6 | Prototype p1 = p.clone(); 7 | System.out.println(p1.getName()); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/proxy/ProxySubject.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.proxy; 2 | 3 | public class ProxySubject extends Subject { 4 | private RealSubject realSubject; // 以真实角色作为代理角色的属性 5 | 6 | public ProxySubject() { 7 | } 8 | 9 | public void request() { // 该方法封装了真实对象的request方法 10 | preRequest(); 11 | if (realSubject == null) { 12 | realSubject = new RealSubject(); 13 | } 14 | realSubject.request(); 15 | postRequest(); 16 | } 17 | 18 | public void preRequest() { 19 | System.out.println("Pre request in proxy"); 20 | } 21 | 22 | public void postRequest() { 23 | System.out.println("Post request in proxy"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/proxy/RealSubject.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.proxy; 2 | 3 | public class RealSubject extends Subject { 4 | public RealSubject() { 5 | } 6 | 7 | public void request() { 8 | System.out.println("request in real subject"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/proxy/Subject.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.proxy; 2 | 3 | public abstract class Subject { 4 | public abstract void request(); 5 | } 6 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/simple_factory/Test.java: -------------------------------------------------------------------------------- 1 | public class Test { 2 | public static void main(String[] args) { 3 | UserDao userDao = UserDaoFactory.createUserDao("ORACLE"); 4 | userDao.insert(new User("Client0x01")); 5 | userDao.deleteById("Client0x01"); 6 | userDao = UserDaoFactory.createUserDao("DB2"); 7 | userDao.insert(new User("guest0x01")); 8 | userDao.deleteById("guest0x01"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/simple_factory/User.java: -------------------------------------------------------------------------------- 1 | public class User { 2 | private String Id; 3 | public User(String Id) { 4 | this.Id = Id; 5 | } 6 | public String getId() { 7 | return this.Id; 8 | } 9 | public void setId(String Id) { 10 | this.Id = Id; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/simple_factory/UserDB2Dao.java: -------------------------------------------------------------------------------- 1 | public class UserDB2Dao implements UserDao { 2 | public void insert(User u) { 3 | System.out.println("insert user: " + u.getId() + " into DB2 db"); 4 | } 5 | public void deleteById(String Id) { 6 | System.out.println("delete user: " + Id + " from DB2 db"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/simple_factory/UserDao.java: -------------------------------------------------------------------------------- 1 | public interface UserDao { 2 | public void insert(User u); 3 | public void deleteById(String Id); 4 | } 5 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/simple_factory/UserDaoFactory.java: -------------------------------------------------------------------------------- 1 | public class UserDaoFactory { 2 | public static UserDao createUserDao(String type) { 3 | if ("ORACLE".equals(type)) { 4 | return new UserOracleDao(); 5 | } 6 | else if ("DB2".equals(type)) { 7 | return new UserDB2Dao(); 8 | } 9 | else { 10 | return null; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/simple_factory/UserOracleDao.java: -------------------------------------------------------------------------------- 1 | public class UserOracleDao implements UserDao { 2 | public void insert(User u) { 3 | System.out.println("insert user: " + u.getId() + " into oracle db"); 4 | } 5 | public void deleteById(String Id) { 6 | System.out.println("delete user: " + Id + " from oracle db"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/singleton/Singleton.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.singleton; 2 | 3 | /* 4 | * Copyright (c) 2015 oxnz. All rights reserved. 5 | */ 6 | 7 | public class Singleton { 8 | 9 | private Singleton() { 10 | } 11 | 12 | private static final Singleton singleton = new Singleton(); 13 | 14 | /** 15 | * Returns an Singleton object that only exist one copy. 16 | *

17 | * 18 | * This method returns a static final object. 19 | * 20 | * @return a Sinleton instance 21 | */ 22 | public static Singleton getInstance() { 23 | return singleton; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/state/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.state; 2 | 3 | //测试用例 模拟servlet容器 4 | public class Test { 5 | public static void main(String[] args) { 6 | IndexServerlet s = new IndexServerlet(); 7 | //用户第一次直接到主页面 8 | s.request(); 9 | //用户有登陆请求 10 | s.request("login"); 11 | s.request("logout"); 12 | s.request("login"); 13 | s.request("logout"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/strategy/Computer.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.strategy; 2 | 3 | //引用实例,持有策略者 4 | public class Computer { 5 | private PowerStrategy powerStrategy; 6 | 7 | public PowerStrategy getPowerStrategy() { 8 | return this.powerStrategy; 9 | } 10 | public void setPowerStrategy(PowerStrategy powerStrategy) { 11 | this.powerStrategy = powerStrategy; 12 | } 13 | public void applyPowerStrategy() { 14 | powerStrategy.apply(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/strategy/EnergySavingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.strategy; 2 | 3 | //策略1 高表现性能策略 4 | public class EnergySavingStrategy implements PowerStrategy { 5 | public void apply() { 6 | System.out.println("*** Energy-saving power strategy ***"); 7 | System.out.println("trun off monitor: 5 minutes"); 8 | System.out.println("trun off harddisk: 15 minutes"); 9 | System.out.println("system standby: 30 minutes"); 10 | System.out.println("system hibernates: 1 hour"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/strategy/HighPerformanceStrategy.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.strategy; 2 | 3 | //策略1 高表现性能策略 4 | public class HighPerformanceStrategy implements PowerStrategy { 5 | public void apply() { 6 | System.out.println("*** High performance power strategy ***"); 7 | System.out.println("trun off monitor: Never"); 8 | System.out.println("trun off harddisk: Never"); 9 | System.out.println("system standby: Never"); 10 | System.out.println("system hibernates: Never"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/strategy/MediumStrategy.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.strategy; 2 | 3 | //策略1 高表现性能策略 4 | public class MediumStrategy implements PowerStrategy { 5 | public void apply() { 6 | System.out.println("*** Medium power strategy ***"); 7 | System.out.println("trun off monitor: 1 hour"); 8 | System.out.println("trun off harddisk: 2 hours"); 9 | System.out.println("system standby: 3 hours"); 10 | System.out.println("system hibernates: 4 hours"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/strategy/PowerStrategy.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.strategy; 2 | 3 | //策略接口 4 | public interface PowerStrategy { 5 | public void apply(); 6 | } 7 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/strategy/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.strategy; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | Computer c = new Computer(); 6 | c.setPowerStrategy(new HighPerformanceStrategy()); 7 | c.applyPowerStrategy(); 8 | 9 | c.setPowerStrategy(new MediumStrategy()); 10 | c.applyPowerStrategy(); 11 | 12 | c.setPowerStrategy(new EnergySavingStrategy()); 13 | c.applyPowerStrategy(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/template/Template.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.template; 2 | 3 | public abstract class Template { 4 | private void beforeOperation() { 5 | System.out.println("action before operation"); 6 | } 7 | 8 | private void afterOperation() { 9 | System.out.println("action after operation"); 10 | } 11 | 12 | //需要推迟到子类(实现类) 中执行 13 | protected abstract void operation(); 14 | 15 | public void action() { 16 | beforeOperation(); 17 | operation(); 18 | afterOperation(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/template/TemplateImpl.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.template; 2 | 3 | public class TemplateImpl extends Template { 4 | protected void operation() { 5 | System.out.println("operation"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/visitor/Failure.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.visitor; 2 | 3 | public class Failure implements Visitor { 4 | public void visit(Man m) { 5 | System.out.println("When a man failed, often drunk himself"); 6 | } 7 | 8 | public void visit(Woman w) { 9 | System.out.println("When a woman failed, often crying"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/visitor/Love.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.visitor; 2 | 3 | public class Love implements Visitor { 4 | public void visit(Man m) { 5 | System.out.println("When a man fall in love, pretend knowing everything"); 6 | } 7 | 8 | public void visit(Woman w) { 9 | System.out.println("When a woman fall in love, pretend knowing nothing"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/visitor/Man.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.visitor; 2 | 3 | public class Man implements Person { 4 | public void accept(Visitor v) { 5 | v.visit(this); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/visitor/Person.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.visitor; 2 | 3 | public interface Person { 4 | public void accept(Visitor v); 5 | } 6 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/visitor/Success.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.visitor; 2 | 3 | public class Success implements Visitor { 4 | public void visit(Man m) { 5 | System.out.println("When a man succeed, there's a great women behind him"); 6 | } 7 | 8 | public void visit(Woman w) { 9 | System.out.println("When a woman succeed, there's a failed man behind her"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/visitor/Test.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.visitor; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | Love love = new Love(); 6 | Success success = new Success(); 7 | 8 | Man man = new Man(); 9 | Woman woman = new Woman(); 10 | 11 | man.accept(success); 12 | woman.accept(success); 13 | man.accept(love); 14 | woman.accept(love); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/visitor/Visitor.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.visitor; 2 | 3 | public interface Visitor { 4 | public void visit(Man m); 5 | 6 | public void visit(Woman w); 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/main/java/com/errpro/design_patterns/visitor/Woman.java: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.visitor; 2 | 3 | public class Woman implements Person { 4 | public void accept(Visitor v) { 5 | v.visit(this); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/java/src/test/java/com/errpro/design_patterns/singleton/SingletonTest.groovy: -------------------------------------------------------------------------------- 1 | package com.errpro.design_patterns.singleton 2 | 3 | /** 4 | * Created by zpw on 15-11-6. 5 | */ 6 | class SingletonTest extends GroovyTestCase { 7 | void testGetInstance() { 8 | def singleTon = Singleton.getInstance() 9 | junit.framework.TestCase.assertTrue(singleTon != null) 10 | def singleTon2 = Singleton.getInstance() 11 | groovy.util.GroovyTestCase.assertEquals(singleTon, singleTon2) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main.cc.template: -------------------------------------------------------------------------------- 1 | #include "" 2 | 3 | int main(int argc, char *argv[]) { 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /src/mediator/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | country.o \ 5 | mediator.o \ 6 | 7 | $(TARGET): $(OBJS) 8 | $(CXX) $^ -o $@ 9 | 10 | clean: 11 | $(RM) $(OBJS) $(TARGET) 12 | -------------------------------------------------------------------------------- /src/mediator/cpp/country.cc: -------------------------------------------------------------------------------- 1 | #include "country.h" 2 | #include "mediator.h" 3 | 4 | void Japan::SetMediator(Mediator* m) 5 | { 6 | m_pMediator = m; 7 | } 8 | 9 | void Japan::SendMessage(std::string msg) 10 | { 11 | std::cout << "Japan Sent: " << msg << std::endl; 12 | m_pMediator->Send(msg, this); 13 | } 14 | 15 | void Japan::GetMessage(std::string msg) 16 | { 17 | std::cout << "Japan Got: " << msg << std::endl; 18 | } 19 | 20 | void China::SetMediator(Mediator* m) 21 | { 22 | m_pMediator = m; 23 | } 24 | 25 | void China::SendMessage(std::string msg) 26 | { 27 | std::cout << "China Sent: " << msg << std::endl; 28 | m_pMediator->Send(msg, this); 29 | } 30 | 31 | void China::GetMessage(std::string msg) 32 | { 33 | std::cout << "China Got: " << msg << std::endl; 34 | } 35 | -------------------------------------------------------------------------------- /src/mediator/cpp/country.h: -------------------------------------------------------------------------------- 1 | #ifndef COUNTRY_H 2 | #define COUNTRY_H 3 | 4 | #include 5 | 6 | class Mediator; 7 | 8 | class Country 9 | { 10 | public: 11 | virtual void SetMediator(Mediator* m){} 12 | virtual void SendMessage(std::string msg){} 13 | virtual void GetMessage(std::string msg){} 14 | protected: 15 | Mediator* m_pMediator; 16 | }; 17 | 18 | class Japan : public Country 19 | { 20 | public: 21 | void SetMediator(Mediator* m); 22 | void SendMessage(std::string msg); 23 | void GetMessage(std::string msg); 24 | }; 25 | 26 | class China : public Country 27 | { 28 | public: 29 | void SetMediator(Mediator* m); 30 | void SendMessage(std::string msg); 31 | void GetMessage(std::string msg); 32 | }; 33 | 34 | #endif//COUNTRY_H 35 | -------------------------------------------------------------------------------- /src/mediator/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "country.h" 2 | #include "mediator.h" 3 | 4 | int main(int argc, char *argv[]) { 5 | Mediator* m = new UN(); 6 | Country* pJapan = new Japan(); 7 | Country* pChina = new China(); 8 | 9 | m->SetJanpa(pJapan); 10 | m->SetChina(pChina); 11 | 12 | pJapan->SetMediator(m); 13 | pChina->SetMediator(m); 14 | 15 | pJapan->SendMessage("钓鱼岛是日本的"); 16 | pChina->SendMessage("钓鱼岛是中国的"); 17 | 18 | delete pJapan; 19 | delete pChina; 20 | delete m; 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/mediator/cpp/mediator.cc: -------------------------------------------------------------------------------- 1 | #include "mediator.h" 2 | #include "country.h" 3 | 4 | void UN::SetJanpa(Country* c) 5 | { 6 | m_pJanpa = c; 7 | } 8 | 9 | void UN::SetChina(Country* c) 10 | { 11 | m_pChina = c; 12 | } 13 | 14 | void UN::Send(std::string msg, Country* c) 15 | { 16 | if (c == m_pJanpa) 17 | m_pChina->GetMessage(msg); 18 | else 19 | m_pJanpa->GetMessage(msg); 20 | } 21 | -------------------------------------------------------------------------------- /src/mediator/cpp/mediator.h: -------------------------------------------------------------------------------- 1 | #ifndef MEDIATOR_H 2 | #define MEDIATOR_H 3 | 4 | #include 5 | 6 | class Country; 7 | //抽象中介者 8 | class Mediator 9 | { 10 | public: 11 | virtual void Send(std::string msg, Country* c){} 12 | virtual void SetJanpa(Country *c){} 13 | virtual void SetChina(Country *c){} 14 | }; 15 | 16 | class UN : public Mediator 17 | { 18 | public: 19 | UN() : m_pJanpa(NULL), m_pChina(NULL) {} 20 | void SetJanpa(Country* c); 21 | void SetChina(Country* c); 22 | void Send(std::string msg, Country* c); 23 | private: 24 | Country* m_pJanpa; 25 | Country* m_pChina; 26 | }; 27 | 28 | #endif//MEDIATOR_H 29 | -------------------------------------------------------------------------------- /src/mediator/mediator.md: -------------------------------------------------------------------------------- 1 | #中介者(Mediator)模式 2 | 3 | ##一. 举例 4 | 5 | 比如,现在中图和日本在关于钓鱼岛问题上存在争端。这时,联合国就会站出来,做为调解者,其实也没什么好调解的,钓鱼岛本来就是中国的,这是不争的事实!联合国也就是个传话者、发言人。 6 | 7 | 结构图如下: 8 | ![结构图](./uml1.png) 9 | 10 | 代码如下: 11 | 12 | ##二. 中介者模式 13 | 14 | `定义`:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 15 | ![中介者模式](./uml2.png) 16 | 17 | ###说明: 18 | 19 | 1. Mediator 模式中,每个Colleague 维护一个 Mediator,当要进行通信时,每个具体的 Colleague 直接向ConcreteMediator 发信息,至于信息发到哪里,则由 ConcreteMediator 来决定。 20 | 2. ConcreteColleagueA 和 ConcreteColleagueB 不必维护对各自的引用,甚至它们也不知道各个的存在。 21 | 3. 优点是,各个 Colleague 减少了耦合。 22 | 4. 缺点是,由于 Mediator 控制了集中化,于是就把 Colleague 之间的交互复杂性变为了中介者的复杂性,也就是中介者会变的比任何一个 Colleague 都复杂。 23 | -------------------------------------------------------------------------------- /src/mediator/perl/Colleague.pm: -------------------------------------------------------------------------------- 1 | package Colleague; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $mediator) = @_; 8 | my $self = { 9 | mediator => $mediator, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub send { 15 | my ($self, $message) = @_; 16 | $self->{mediator}->send($message, $self); 17 | } 18 | 19 | sub notify { 20 | die "DO NOT CALL ABSTRACT METHOD NOTIFY DIRECTLY\n"; 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /src/mediator/perl/Mediator.pm: -------------------------------------------------------------------------------- 1 | package Mediator; 2 | 3 | use strict; 4 | use warnings; 5 | use Data::Dump; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = {}; 10 | return bless $self, $class; 11 | } 12 | 13 | sub colleagues { 14 | my ($self, $colleagues) = @_; 15 | $self->{colleagues} = $colleagues if defined($colleagues); 16 | return $self->{colleagues}; 17 | } 18 | 19 | sub send { 20 | die "DO NOT CALL ABSTRACT METHOD SEND DIRECTLY\n"; 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /src/mediator/perl/colleague/ConcreteColleague1.pm: -------------------------------------------------------------------------------- 1 | package Colleague::ConcreteColleague1; 2 | use parent Colleague; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $mediator) = @_; 9 | my $self = $class->SUPER::new($mediator); 10 | return $self; 11 | } 12 | 13 | sub notify { 14 | my ($self, $message) = @_; 15 | print "Colleague 1 received message: ", $message, "\n"; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /src/mediator/perl/colleague/ConcreteColleague2.pm: -------------------------------------------------------------------------------- 1 | package Colleague::ConcreteColleague2; 2 | use parent Colleague; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $mediator) = @_; 9 | my $self = $class->SUPER::new($mediator); 10 | return $self; 11 | } 12 | 13 | sub notify { 14 | my ($self, $message) = @_; 15 | print "Colleague 2 received message: ", $message, "\n"; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /src/mediator/perl/mediator/ConcreteMediator.pm: -------------------------------------------------------------------------------- 1 | package Mediator::ConcreteMediator; 2 | use parent Mediator; 3 | 4 | use strict; 5 | use warnings; 6 | use Data::Dump; 7 | 8 | sub new { 9 | my ($class, $args) = @_; 10 | my $self = $class->SUPER::new($args); 11 | return $self; 12 | } 13 | 14 | sub send { 15 | my ($self, $message, $colleague) = @_; 16 | my $colleagues = $self->colleagues; 17 | foreach (@$colleagues) { 18 | if ($_ == $colleague) { 19 | # skip self 20 | } else { 21 | $_->notify($message); 22 | } 23 | } 24 | } 25 | 26 | 1; 27 | -------------------------------------------------------------------------------- /src/mediator/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use Mediator::ConcreteMediator; 6 | use Colleague::ConcreteColleague1; 7 | use Colleague::ConcreteColleague2; 8 | 9 | my $mediator = Mediator::ConcreteMediator->new; 10 | my $c1 = Colleague::ConcreteColleague1->new($mediator); 11 | my $c2 = Colleague::ConcreteColleague2->new($mediator); 12 | $mediator->colleagues([$c1, $c2]); 13 | $c1->send("Hi, Colleague2, I'm colleague 1"); 14 | $c2->send("Hi, Colleague1, I'm colleague 2"); 15 | -------------------------------------------------------------------------------- /src/mediator/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/mediator/uml1.png -------------------------------------------------------------------------------- /src/mediator/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/mediator/uml2.png -------------------------------------------------------------------------------- /src/memento/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | memento.o \ 5 | originator.o \ 6 | 7 | $(TARGET): $(OBJS) 8 | $(CXX) $^ -o $@ 9 | 10 | clean: 11 | $(RM) $(OBJS) $(TARGET) 12 | -------------------------------------------------------------------------------- /src/memento/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "memento.h" 2 | #include "originator.h" 3 | 4 | int main(int argc, char *argv[]) { 5 | Originator* o = new Originator(); 6 | o->SetState("old"); //备忘以前的状态 7 | o->PrintState(); 8 | 9 | Memento* m = o->CreateMemento(); //创建一个备忘录 10 | o->SetState("new"); //修改状态 11 | o->PrintState(); 12 | 13 | o->RestoreToMemento(m); //恢复修改前的状态 14 | o->PrintState(); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/memento/cpp/memento.cc: -------------------------------------------------------------------------------- 1 | #include "memento.h" 2 | 3 | Memento::Memento(const std::string& state) 4 | { 5 | m_sState = state; 6 | } 7 | 8 | void Memento::SetState(const std::string& state) 9 | { 10 | m_sState = state; 11 | } 12 | 13 | std::string Memento::GetState() const 14 | { 15 | return m_sState; 16 | } 17 | -------------------------------------------------------------------------------- /src/memento/cpp/memento.h: -------------------------------------------------------------------------------- 1 | #include 2 | #ifndef MEMENTO_H 3 | #define MEMENTO_H 4 | 5 | class Originator; 6 | 7 | class Memento 8 | { 9 | public: 10 | private: 11 | friend class Originator; 12 | Memento(){} 13 | Memento(const std::string& state); 14 | void SetState(const std::string& state); 15 | std::string GetState() const; 16 | private: 17 | std::string m_sState; 18 | }; 19 | 20 | #endif//MEMENTO_H 21 | -------------------------------------------------------------------------------- /src/memento/cpp/originator.cc: -------------------------------------------------------------------------------- 1 | #include "originator.h" 2 | #include "memento.h" 3 | 4 | Originator::Originator() 5 | : m_sState(""), m_pMemento(0) {} 6 | 7 | Originator::Originator(const std::string& state) 8 | : m_sState(state), m_pMemento(0) {} 9 | 10 | Memento* Originator::CreateMemento() 11 | { 12 | return new Memento(m_sState); 13 | } 14 | 15 | void Originator::RestoreToMemento(Memento* m) 16 | { 17 | m_sState = m->GetState(); 18 | } 19 | 20 | std::string Originator::GetState() const 21 | { 22 | return m_sState; 23 | } 24 | 25 | void Originator::SetState(const std::string& state) 26 | { 27 | m_sState = state; 28 | } 29 | 30 | void Originator::PrintState() const 31 | { 32 | std::cout << m_sState << "......" << std::endl; 33 | } 34 | -------------------------------------------------------------------------------- /src/memento/cpp/originator.h: -------------------------------------------------------------------------------- 1 | #ifndef ORIGINATOR_H 2 | #define ORIGINATOR_H 3 | 4 | #include 5 | 6 | class Memento; 7 | 8 | class Originator 9 | { 10 | public: 11 | Originator(); 12 | Originator(const std::string& state); 13 | Memento* CreateMemento(); 14 | void RestoreToMemento(Memento* m); 15 | std::string GetState() const; 16 | void SetState(const std::string& state); 17 | void PrintState() const; 18 | private: 19 | std::string m_sState; 20 | Memento* m_pMemento; 21 | }; 22 | 23 | #endif//ORIGINATOR_H 24 | -------------------------------------------------------------------------------- /src/memento/memento.md: -------------------------------------------------------------------------------- 1 | #备忘录(Memento)模式 2 | 3 | ##一. 备忘录模式 4 | 5 | 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 6 | 7 | 结构图: 8 | ![结构图](./uml.png) 9 | 10 | ###使用范围: 11 | 12 | Memento 模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator 可以根据保存的 Memento 信息还原到前一状态。 13 | 14 | 代码: 15 | 16 | ##二. 说明 17 | 18 | 1. Memento 负责存储 Originator 对象的内部状态,并可防止 Originator 以外的其它对象访问备忘录(具体实现方法,就是让其所有方法都为私有的)。 19 | 2. Memento 声明 Originator 为它的友元类,这样 Originator 就可以访问它的所有函数,即对 Originator 是开放的。 20 | 21 | 我觉得,私有和友元是备忘录模式实现的关键! -------------------------------------------------------------------------------- /src/memento/perl/Caretaker.pm: -------------------------------------------------------------------------------- 1 | package Caretaker; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class) = @_; 8 | my $self = { 9 | memento => undef, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub memento { 15 | my ($self, $memento) = @_; 16 | $self->{memento} = $memento if defined $memento; 17 | return $self->{memento}; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /src/memento/perl/Memento.pm: -------------------------------------------------------------------------------- 1 | package Memento; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $state) = @_; 8 | my $self = { 9 | state => $state, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub state { 15 | my ($self, $state) = @_; 16 | $self->{state} = $state if defined $state; 17 | return $self->{state}; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /src/memento/perl/Originator.pm: -------------------------------------------------------------------------------- 1 | package Originator; 2 | 3 | use strict; 4 | use warnings; 5 | use Memento; 6 | 7 | sub new { 8 | my ($class) = @_; 9 | my $self = { 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub createMemento { 15 | my $self = shift; 16 | return Memento->new($self->{state}); 17 | } 18 | 19 | sub restoreMemento { 20 | my ($self, $memento) = @_; 21 | $self->{state} = $memento->state; 22 | } 23 | 24 | sub state { 25 | my ($self, $state) = @_; 26 | $self->{state} = $state if defined $state; 27 | return $self->{state}; 28 | } 29 | 30 | sub showState { 31 | my $self = shift; 32 | print ref $self, " status: ", $self->state, "\n"; 33 | } 34 | 35 | 1; 36 | -------------------------------------------------------------------------------- /src/memento/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # auther: oxnz 3 | # coding: utf-8 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use Originator; 9 | use Caretaker; 10 | 11 | my $orig = Originator->new; 12 | $orig->state("open"); 13 | $orig->showState; 14 | my $memento = $orig->createMemento; 15 | my $caretaker = Caretaker->new; 16 | $caretaker->memento($memento); 17 | $orig->state('close'); 18 | $orig->showState; 19 | $orig->restoreMemento($caretaker->memento); 20 | $orig->showState; 21 | -------------------------------------------------------------------------------- /src/memento/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/memento/uml.png -------------------------------------------------------------------------------- /src/null-object/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | animal.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/null-object/cpp/animal.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "animal.h" 3 | 4 | using namespace std; 5 | 6 | void Dog::make_sound() 7 | { 8 | cout << "woof!" << endl; 9 | } 10 | -------------------------------------------------------------------------------- /src/null-object/cpp/animal.h: -------------------------------------------------------------------------------- 1 | #ifndef ANIMAL_H 2 | #define ANIMAL_H 3 | 4 | class Animal 5 | { 6 | public: 7 | virtual void make_sound() = 0; 8 | virtual ~Animal(){} 9 | }; 10 | 11 | class Dog : public Animal 12 | { 13 | void make_sound(); 14 | }; 15 | 16 | class null_animal : public Animal 17 | { 18 | void make_sound(){} 19 | }; 20 | 21 | #endif//ANIMAL_H 22 | -------------------------------------------------------------------------------- /src/null-object/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "animal.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | Animal *pDog = new Dog(); 5 | pDog->make_sound(); 6 | 7 | delete pDog; 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/null-object/null-object.md: -------------------------------------------------------------------------------- 1 | #Null Object Pattern -------------------------------------------------------------------------------- /src/null-object/php/Logger.php: -------------------------------------------------------------------------------- 1 | logger = $logger; 20 | } 21 | 22 | /** 23 | * do something 24 | */ 25 | public function doSomething() { 26 | /** 27 | * no more check "if (!is_null($this->logger))..." with the NullObject 28 | */ 29 | $this->logger->log('We are in ' . __METHOD__); 30 | // do actual action 31 | } 32 | } 33 | 34 | ?> 35 | -------------------------------------------------------------------------------- /src/null-object/ruby/NullObject.rb: -------------------------------------------------------------------------------- 1 | class NullObject 2 | def method_missing(*args, &block) 3 | self 4 | end 5 | def to_a 6 | [] 7 | end 8 | def to_s 9 | "" 10 | end 11 | def to_f 12 | 0.0 13 | end 14 | def to_i 15 | 0 16 | end 17 | def nil? 18 | true 19 | end 20 | def present? 21 | false 22 | end 23 | def empty? 24 | true 25 | end 26 | def ! 27 | true 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /src/null-object/ruby/test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require './NullObject.rb' 4 | 5 | no = NullObject.new 6 | p no 7 | no.foo 8 | no.bar 9 | -------------------------------------------------------------------------------- /src/object-pool/object-pool.md: -------------------------------------------------------------------------------- 1 | #对象池模式(object pool) 2 | 3 | 单例模式是限制了一个类只能有一个实例,对象池模式则是限制一个类实例的个数。对象池类就像是一个对象管理员,它以Static列表(也就是装对象的池子)的形式存存储某个实例数受限的类的实例,每一个实例还要加一个标记,标记该实例是否被占用。当类初始化的时候,这个对象池就被初始化了,实例就被创建出来。然后,用户可以向这个类索取实例,如果池中所有的实例都已经被占用了,那么抛出异常。用户用完以后,还要把实例“还”回来,即释放占用。 4 | 5 | 对象池类的成员应该都是静态的。用户也不应该能访问池子里装着的对象的构造函数,以防用户绕开对象池创建实例。 6 | 7 | 书上说这个模式会用在数据库连接的管理上。比如,每个用户的连接数是有限的,这样每个连接就是一个池子里的一个对象,“连接池”类就可以控制连接数了。 -------------------------------------------------------------------------------- /src/observer/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | observer.o \ 5 | subject.o \ 6 | 7 | $(TARGET): $(OBJS) 8 | $(CXX) $^ -o $@ 9 | 10 | clean: 11 | $(RM) $(OBJS) $(TARGET) 12 | -------------------------------------------------------------------------------- /src/observer/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "observer.h" 2 | #include "subject.h" 3 | 4 | int main(int argc, char *argv[]) { 5 | DataSubject* s = new DataSubject(); //数据通知者 6 | 7 | Observer* o1 = new SheetObserver(s); //表格观察者 8 | Observer* o2 = new ChatObserver(s); //图表观察者 9 | 10 | s->SetState("old data"); //数据发生变化 11 | s->Notify(); //通知者下发通知 12 | s->SetState("new data"); 13 | s->Notify(); 14 | 15 | o1->Update(s); //也可以由观察者自己调用更新函数 16 | 17 | delete o1; 18 | delete o2; 19 | delete s; 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/observer/cpp/subject.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBJECT_H 2 | #define SUBJECT_H 3 | 4 | #include 5 | #include 6 | 7 | class Observer; 8 | 9 | class Subject 10 | { 11 | public: 12 | //注册观察者,这样通知者就能通知到观察者 13 | virtual void Attach(Observer*); 14 | virtual void Detach(Observer*); 15 | virtual void Notify(); 16 | virtual void SetState(const std::string& state) = 0; 17 | virtual std::string GetState() const = 0; 18 | virtual ~Subject(); 19 | protected: 20 | Subject(); 21 | private: 22 | std::list* m_pObserverList; 23 | }; 24 | 25 | class DataSubject : public Subject 26 | { 27 | public: 28 | DataSubject(); 29 | std::string GetState() const; 30 | void SetState(const std::string& state); 31 | virtual ~DataSubject(); 32 | private: 33 | std::string m_sState; 34 | }; 35 | 36 | #endif//SUBJECT_H 37 | -------------------------------------------------------------------------------- /src/observer/perl/Observer.pm: -------------------------------------------------------------------------------- 1 | package Observer; 2 | 3 | use Data::Dump; 4 | 5 | sub new { 6 | my ($class, $args) = @_; 7 | my $self = { 8 | name => $args->{name} || "anonymous observer", 9 | }; 10 | return bless $self, $class; 11 | } 12 | 13 | sub DESTROY { 14 | my $self = shift; 15 | print "destroy ", $self->name, "\n"; 16 | } 17 | 18 | sub name { 19 | my ($self, $name) = @_; 20 | $self->name = $name if defined($name); 21 | return $self->{name}; 22 | } 23 | 24 | sub update { 25 | my ($self, $subject) = @_; 26 | print "observer ", $self->name, 27 | " has recieved notification from subject ", $subject->name, "\n"; 28 | } 29 | 30 | 1; 31 | -------------------------------------------------------------------------------- /src/observer/perl/Observer/DataObserver.pm: -------------------------------------------------------------------------------- 1 | package Observer::DataObserver; 2 | use parent Observer; 3 | 4 | sub new { 5 | my ($class, $args) = @_; 6 | my $self = $class->SUPER::new($args); 7 | return $self; 8 | } 9 | 10 | sub update { 11 | my ($self, $subject) = @_; 12 | $self->SUPER::update($subject); 13 | print "\twith data: ", $subject->data, "\n"; 14 | #print "DataSubject: ", $subject->name, " has data: ", $subject->data, "\n"; 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /src/observer/perl/Subject/DataSubject.pm: -------------------------------------------------------------------------------- 1 | package Subject::DataSubject; 2 | use parent Subject; 3 | 4 | use strict; 5 | use warnings; 6 | use Data::Dump; 7 | 8 | sub new { 9 | my ($class, $args) = @_; 10 | my $self = $class->SUPER::new($args); 11 | $self->{name} = $args->{name}; 12 | $self->{data} = $args->{data}; 13 | return $self; 14 | } 15 | 16 | sub data { 17 | my ($self, $data) = @_; 18 | if (defined($data)) { 19 | $self->{data} = $data; 20 | $self->notify; 21 | } 22 | return $self->{data}; 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /src/observer/php/client.php: -------------------------------------------------------------------------------- 1 | obj1 = new ObserverA(); 13 | $this->obj2 = new ObserverB(); 14 | $this->sub = new SubjectA(); 15 | } 16 | 17 | public function test() { 18 | $this->sub->attach($this->obj1); 19 | $this->sub->attach($this->obj2); 20 | $this->sub->setState("working"); 21 | $this->sub->detach($this->ob2); 22 | $this->sub->setState("studying"); 23 | $this->sub->detach($this->obj1); 24 | $this->sub->setState("eating"); 25 | } 26 | 27 | public function __destruct() { 28 | $obj1 = null; 29 | $obj2 = null; 30 | $obj3 = null; 31 | } 32 | } 33 | 34 | $client = new Client(); 35 | $client->test(); 36 | $client = null; 37 | 38 | ?> 39 | -------------------------------------------------------------------------------- /src/observer/php/observer.php: -------------------------------------------------------------------------------- 1 | getState()); 10 | } 11 | 12 | public function __destruct() { 13 | } 14 | } 15 | 16 | class ObserverB implements Observer { 17 | public function update($subject) { 18 | printf("Observer B got: %s\n", $subject->getState()); 19 | } 20 | 21 | public function __destruct() { 22 | } 23 | } 24 | ?> 25 | -------------------------------------------------------------------------------- /src/observer/ruby/car.rb: -------------------------------------------------------------------------------- 1 | require 'observer' 2 | 3 | class Notifier 4 | def update(car, miles) 5 | puts "The car has logged #{miles} miles, totaling #{car.mileage} miles traveled." 6 | puts "The car needs to be taken in for a service!" if car.service \ 7 | < car.mileage 8 | end 9 | end 10 | 11 | class Car 12 | include Observable 13 | attr_reader :mileage, :service 14 | 15 | def initialize(mileage = 0, service = 3000) 16 | @mileage, @service = mileage, service 17 | add_observer(Notifier.new) 18 | end 19 | 20 | def log(miles) 21 | @mileage += miles 22 | changed 23 | notify_observers(self, miles) 24 | end 25 | end 26 | 27 | car = Car.new(2300, 3000) 28 | car.log(100) 29 | car.log(354) 30 | car.log(300) 31 | -------------------------------------------------------------------------------- /src/observer/ruby/notifier.rb: -------------------------------------------------------------------------------- 1 | class Notifier 2 | def update(car, miles) 3 | puts "The car has logged #{miles} miles, totaling #{car.mileage} 4 | miles traveled." 5 | puts "The car needs to be taken in for a service!" if car.service 6 | &< car.mileage 7 | &lt;= car.mileage 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /src/observer/ruby/test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'Car' 4 | -------------------------------------------------------------------------------- /src/observer/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/observer/uml1.png -------------------------------------------------------------------------------- /src/observer/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/observer/uml2.png -------------------------------------------------------------------------------- /src/observer/uml3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/observer/uml3.png -------------------------------------------------------------------------------- /src/private-class-data/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | 5 | $(TARGET): $(OBJS) 6 | $(CXX) $^ -o $@ 7 | 8 | clean: 9 | $(RM) $(OBJS) $(TARGET) 10 | -------------------------------------------------------------------------------- /src/private-class-data/cpp/main.cc: -------------------------------------------------------------------------------- 1 | 2 | int main(int argc, char *argv[]) { 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /src/prototype/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | prototype.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/prototype/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "prototype.h" 2 | 3 | int main(void) { 4 | //拷贝构造操作 5 | ConcretePrototype p1; 6 | ConcretePrototype p2 = p1; 7 | 8 | //克隆操作 9 | Prototype* p3 = new ConcretePrototype(); 10 | Prototype* p4 = p3->Clone(); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/prototype/cpp/prototype.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "prototype.h" 3 | 4 | ConcretePrototype::ConcretePrototype(const ConcretePrototype& cp) 5 | { 6 | std::cout << "ConcretePrototype copy constructor" << std::endl; 7 | } 8 | 9 | Prototype* ConcretePrototype::Clone() const 10 | { 11 | std::cout << "ConcretePrototype Clone method" << std::endl; 12 | return new ConcretePrototype(*this); 13 | } 14 | -------------------------------------------------------------------------------- /src/prototype/cpp/prototype.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOTYPE_H 2 | #define PROTOTYPE_H 3 | 4 | class Prototype 5 | { 6 | public: 7 | virtual ~Prototype(){} 8 | virtual Prototype* Clone() const = 0; 9 | }; 10 | 11 | class ConcretePrototype : public Prototype 12 | { 13 | public: 14 | ConcretePrototype(){} 15 | ConcretePrototype(const ConcretePrototype& cp); 16 | Prototype* Clone() const; 17 | }; 18 | 19 | #endif//PROTOTYPE_H 20 | -------------------------------------------------------------------------------- /src/prototype/perl/ProtoType.pm: -------------------------------------------------------------------------------- 1 | package ProtoType; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = { 9 | name => $args->{name} || "anonymous", 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub name { 15 | my ($self, $name) = @_; 16 | $self->{name} = $name if defined $name; 17 | return $self->{name}; 18 | } 19 | 20 | sub clone { 21 | die "INTERFACE METHOD CLONE CANNOT BE CALLED DIRECTLY\n"; 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /src/prototype/perl/ProtoType/ConcreteProtoType.pm: -------------------------------------------------------------------------------- 1 | package ProtoType::ConcreteProtoType; 2 | use parent ProtoType; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | return $self; 11 | } 12 | 13 | sub clone { 14 | my $class = ref shift; 15 | return $class->new; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /src/prototype/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use ProtoType::ConcreteProtoType; 6 | use Data::Dump; 7 | 8 | my $p1 = ProtoType::ConcreteProtoType->new; 9 | my $p2 = $p1->clone; 10 | $p1->name("abc"); 11 | $p2->name("def"); 12 | dd $p1; 13 | dd $p2; 14 | -------------------------------------------------------------------------------- /src/prototype/prototype.md: -------------------------------------------------------------------------------- 1 | #原型(Prototype)模式 2 | 3 | ##一. 概述 4 | 5 | 定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 6 | 7 | 换句话说,就是不用重新初始化对象,而是动态地获得对象运行时的状态。 8 | 9 | 再说明白点,就是要一个拷贝过构造函数类似功能的接口。 10 | 结构图如下: 11 | ![结构图](./uml.png) 12 | 13 | ##二. 说明 14 | 15 | 1. Prototype 模式的关键就是(C++中)拷贝构造函数的实现方式,这也是C++实现技术层面上的事情。 16 | 2. 示例代码中不涉及到深层拷贝(主要指有指针、复合对象的情况),主要在于体现Prototype模式的思想。 -------------------------------------------------------------------------------- /src/prototype/python/test.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | 3 | class Prototype: 4 | def __init__(self): 5 | self._objs = {} 6 | 7 | def registerObject(self, name, obj): 8 | """ 9 | register an object. 10 | """ 11 | self._objs[name] = obj 12 | 13 | def unregisterObject(self, name): 14 | """unregister an object""" 15 | del self._objs[name] 16 | 17 | def clone(self, name, **attr): 18 | """clone a registered object and add/replace attr""" 19 | obj = deepcopy(self._objs[name]) 20 | obj.__dict__.update(attr) 21 | return obj 22 | 23 | if __name__ == '__main__': 24 | class A: 25 | pass 26 | 27 | a=A() 28 | prototype=Prototype() 29 | prototype.registerObject("a",a) 30 | b=prototype.clone("a",a=1,b=2,c=3) 31 | 32 | print(a) 33 | print(b.a, b.b, b.c) 34 | -------------------------------------------------------------------------------- /src/prototype/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/prototype/uml.png -------------------------------------------------------------------------------- /src/proxy/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | proxy.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | clean: 9 | $(RM) $(OBJS) $(TARGET) 10 | .PHONY: clean 11 | -------------------------------------------------------------------------------- /src/proxy/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "proxy.h" 2 | 3 | int main(void) { 4 | Subject *pProxy = new Proxy(); 5 | pProxy->Request(); 6 | delete pProxy; 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /src/proxy/cpp/proxy.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "proxy.h" 3 | 4 | RealSubject::RealSubject() 5 | { 6 | std::cout << "Constructing a RealSubject" << std::endl; 7 | } 8 | 9 | void RealSubject::Request() 10 | { 11 | std::cout << "Request by RealSubject" << std::endl; 12 | } 13 | 14 | Proxy::Proxy() 15 | : m_pRealSubject(NULL) 16 | { 17 | std::cout << "Constructing a Proxy" << std::endl; 18 | } 19 | 20 | Proxy::~Proxy() 21 | { 22 | delete m_pRealSubject; 23 | m_pRealSubject = NULL; 24 | } 25 | 26 | void Proxy::Request() 27 | { 28 | if (NULL == m_pRealSubject) { 29 | std::cout << "Request by Proxy" << std::endl; 30 | m_pRealSubject = new RealSubject(); 31 | } 32 | m_pRealSubject->Request(); 33 | } 34 | -------------------------------------------------------------------------------- /src/proxy/cpp/proxy.h: -------------------------------------------------------------------------------- 1 | #ifndef PROXY_H 2 | #define PROXY_H 3 | 4 | // 定义了Proxy和RealSubject的公有接口, 5 | // 这样就可以在任何需要使用到RealSubject的地方都使用Proxy. 6 | class Subject 7 | { 8 | public: 9 | Subject(){} 10 | virtual ~Subject(){} 11 | virtual void Request() = 0; 12 | }; 13 | 14 | class RealSubject : public Subject 15 | { 16 | public: 17 | RealSubject(); 18 | virtual ~RealSubject(){} 19 | virtual void Request(); 20 | }; 21 | 22 | // 代理类,含有一个指向RealSubject对象的指针 23 | class Proxy : public Subject 24 | { 25 | public: 26 | Proxy(); 27 | virtual ~Proxy(); 28 | virtual void Request(); 29 | private: 30 | RealSubject *m_pRealSubject; 31 | }; 32 | 33 | #endif//PROXY_H 34 | -------------------------------------------------------------------------------- /src/proxy/perl/Proxy.pm: -------------------------------------------------------------------------------- 1 | package Proxy; 2 | 3 | sub new { 4 | my $type = shift; 5 | my $this = { }; 6 | my $obj = shift; ref $obj or die; 7 | $this->{'obj'} = $ojb; 8 | $type .= '::' . ref $obj; 9 | # copy inheritance info. 10 | @{ref{$this}.'::ISA'} = @{ref($obj).'::ISA'}; 11 | bless $this, $type; 12 | } 13 | 14 | # bug XXX - autoload is only used after @ISA is searched! 15 | 16 | sub AUTOLOAD { 17 | my $this = shift; 18 | (my $methodName) = $AUTOLOAD = ~ m/.*::(\w+)$/; 19 | return if $methodName eq 'DESTROY'; 20 | $this->{'obj'}->$methodName(@_); 21 | } 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /src/proxy/perl/Subject.pm: -------------------------------------------------------------------------------- 1 | package Subject; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = {}; 9 | return bless $self, $class; 10 | } 11 | 12 | sub request { 13 | die "INTERFACE METHOD REQUEST CANNOT BE CALLED DIRECTLY\n"; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /src/proxy/perl/Subject/Proxy.pm: -------------------------------------------------------------------------------- 1 | package Subject::Proxy; 2 | use parent Subject; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $subject) = @_; 9 | my $self = $class->SUPER::new; 10 | $self->{subject} = $subject; 11 | return $self; 12 | } 13 | 14 | sub request { 15 | my $self = shift; 16 | $self->{subject}->request; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /src/proxy/perl/Subject/RealSubject.pm: -------------------------------------------------------------------------------- 1 | package Subject::RealSubject; 2 | use parent Subject; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | return $self; 11 | } 12 | 13 | sub request { 14 | print "Handling request in real subject\n"; 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /src/proxy/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use Subject::RealSubject; 6 | use Subject::Proxy; 7 | 8 | my $proxy = Subject::Proxy->new(Subject::RealSubject->new); 9 | $proxy->request(); 10 | -------------------------------------------------------------------------------- /src/proxy/php/proxy.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | subject = $subject; 24 | } 25 | 26 | // pass request to real subject 27 | public function request() { 28 | $this->subject->request(); 29 | } 30 | } 31 | 32 | $proxy = new Proxy(new RealSubject()); 33 | $proxy->request(); 34 | 35 | ?> 36 | -------------------------------------------------------------------------------- /src/proxy/python/implementation.py: -------------------------------------------------------------------------------- 1 | class Implementation: 2 | def f(self): 3 | print "Implementation.f()" 4 | def g(self): 5 | print "Implementation.g()" 6 | -------------------------------------------------------------------------------- /src/proxy/python/proxy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | ''' 5 | Python中的委派机制(delegation)使得Proxy的实现可以非常的简洁优美。 6 | 如下,利用__getattr__,使得程序具有完整的通用性(generic) 7 | 这是动态语言特有的优势,见Dive Into Python第四章,自省的魅力, 8 | 9 | Python 中万 物皆对象,自省指代码可以查看内存中以对象形式存在的其它模块和函数, 10 | 获取它们的信息,并对它们进行操作。 11 | 利用这种方法,你可以定义没有名称的函数,不按函数声明的参数顺序调用函数, 12 | 甚至引用事先并不知道名称的函数(getattr)。 13 | 14 | getattr(object, name[, default]) -> value 15 | 16 | Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. 17 | When a default argument is given, it is returned when the attribute doesn't 18 | exist; without it, an exception is raised in that case. 19 | ''' 20 | 21 | from implementation import Implementation 22 | 23 | class Proxy: 24 | def __init__(self): 25 | self.__implementation = Implementation() 26 | 27 | def __getattr__(self, name): 28 | return getattr(self.__implementation, name) 29 | -------------------------------------------------------------------------------- /src/proxy/python/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | from proxy import Proxy 5 | 6 | if __name__ == "__main__": 7 | p = Proxy() 8 | p.f() 9 | p.g() 10 | -------------------------------------------------------------------------------- /src/proxy/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/proxy/uml.png -------------------------------------------------------------------------------- /src/simple-factory/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | nokia.o \ 5 | factory.o \ 6 | 7 | $(TARGET): $(OBJS) 8 | $(CXX) $^ -o $@ 9 | 10 | clean: 11 | $(RM) $(OBJS) $(TARGET) 12 | -------------------------------------------------------------------------------- /src/simple-factory/cpp/factory.cc: -------------------------------------------------------------------------------- 1 | #include "nokia.h" 2 | #include "factory.h" 3 | 4 | Nokia* Factory::CreateNokia(const std::string& modelName) 5 | { 6 | if (modelName == "Lumia1020") 7 | return new Lumia1020(); 8 | else if (modelName == "Lumia920") 9 | return new Lumia920(); 10 | else 11 | return new Nokia(); 12 | } 13 | -------------------------------------------------------------------------------- /src/simple-factory/cpp/factory.h: -------------------------------------------------------------------------------- 1 | #ifndef FACTORY_H 2 | #define FACTORY_H 3 | 4 | class Nokia; 5 | 6 | class Factory 7 | { 8 | public: 9 | static Nokia* CreateNokia(const std::string& modelName); 10 | }; 11 | 12 | #endif//FACTORY_H 13 | -------------------------------------------------------------------------------- /src/simple-factory/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "nokia.h" 2 | #include "factory.h" 3 | 4 | int main(void) { 5 | Nokia *pNokia = Factory::CreateNokia("Lumia1020"); 6 | pNokia->Call("123456790"); 7 | 8 | delete pNokia; 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/simple-factory/cpp/nokia.cc: -------------------------------------------------------------------------------- 1 | #include "nokia.h" 2 | 3 | void Nokia::Call(const std::string& phoneNumber) const 4 | { 5 | std::cout << "Using a NOKIA Calling " << phoneNumber << std::endl; 6 | } 7 | 8 | void Lumia920::Call(const std::string& phoneNumber) const 9 | { 10 | std::cout << "Using a Lumia 920 Calling " << phoneNumber << std::endl; 11 | } 12 | 13 | void Lumia1020::Call(const std::string& phoneNumber) const 14 | { 15 | std::cout << "Using a Lumia 1020 Calling " << phoneNumber << std::endl; 16 | } 17 | -------------------------------------------------------------------------------- /src/simple-factory/cpp/nokia.h: -------------------------------------------------------------------------------- 1 | #ifndef NOKIA_H 2 | #define NOKIA_H 3 | 4 | #include 5 | 6 | class Nokia 7 | { 8 | public: 9 | virtual void Call(const std::string& phoneNumber) const; 10 | virtual ~Nokia(){} 11 | }; 12 | 13 | class Lumia920 : public Nokia 14 | { 15 | public: 16 | virtual void Call(const std::string& phoneNumber) const; 17 | }; 18 | 19 | class Lumia1020 : public Nokia 20 | { 21 | public: 22 | virtual void Call(const std::string& phoneNumber) const; 23 | }; 24 | 25 | #endif//NOKIA_H 26 | -------------------------------------------------------------------------------- /src/simple-factory/perl/Factory.pm: -------------------------------------------------------------------------------- 1 | package Factory; 2 | 3 | use strict; 4 | use warnings; 5 | use Nokia::Lumia; 6 | use Nokia::Symbian; 7 | 8 | sub new { 9 | my ($class, $args) = @_; 10 | my $self = {}; 11 | return bless $self, $class; 12 | } 13 | 14 | sub create { 15 | my ($self, $model) = @_; 16 | return "Nokia::$model"->new; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /src/simple-factory/perl/Nokia.pm: -------------------------------------------------------------------------------- 1 | package Nokia; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = {}; 9 | return bless $self, $class; 10 | } 11 | 12 | sub call { 13 | die "ABSTRACT CLASS METHOD CALL CANNOT BE CALLED DIRECTLY\n"; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /src/simple-factory/perl/Nokia/Lumia.pm: -------------------------------------------------------------------------------- 1 | package Nokia::Lumia; 2 | use parent Nokia; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new; 10 | return $self; 11 | } 12 | 13 | sub call { 14 | my ($self, $number) = @_; 15 | print "calling ", $number, " with a ", ref $self, "\n"; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /src/simple-factory/perl/Nokia/Symbian.pm: -------------------------------------------------------------------------------- 1 | package Nokia::Symbian; 2 | use parent Nokia; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new; 10 | return $self; 11 | } 12 | 13 | sub call { 14 | my ($self, $number) = @_; 15 | print "calling ", $number, " with a ", ref $self, "\n"; 16 | } 17 | 18 | 1; 19 | -------------------------------------------------------------------------------- /src/simple-factory/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use Factory; 6 | 7 | my $nokiaFactory = Factory->new; 8 | my $nokia = $nokiaFactory->create("Lumia"); 9 | $nokia->call(911); 10 | $nokia = $nokiaFactory->create("Symbian"); 11 | $nokia->call(911); 12 | 13 | -------------------------------------------------------------------------------- /src/simple-factory/php/test.php: -------------------------------------------------------------------------------- 1 | call("911"); 30 | } 31 | } 32 | 33 | Client::main(); 34 | ?> 35 | -------------------------------------------------------------------------------- /src/simple-factory/simple-factory.md: -------------------------------------------------------------------------------- 1 | #简单工厂模式 2 | 3 | 一.简单工厂模式又称静态工厂方法模式(Static Factory Method),它不是Gof 所讲的23种设计模式之一,但是它却是我们在编码过程中经常使用的方法之一。 4 | 5 | 简单工厂就是简单的创造并返回对象, 没有复杂的结构和逻辑. 6 | 7 | 8 | 1.静态工厂方法统一管理对象的创建。 9 | 静态工厂方法通过传入的参数判断决定创建哪一个产品的实例,封装了对象的创建,客户端只管消费,实现了对责任(模块)的分割。 10 | 11 | 2.静态工厂方法推迟了产品的实例化。 12 | 通过XML配置文件就能改变具体要创建的产品实例,修改为其它的产品实例,代码不须重新编译。 13 | 14 | 15 | 16 | 二.简单工厂模式还是有缺点的,后面的工厂方法模式和抽象工厂模式就是对这些缺点的改善。讲完了这三种模式将会有一个对比。以下以Nokia手机为例,采用简单工厂模式设计的源代码雏形。 -------------------------------------------------------------------------------- /src/singleton/TODO: -------------------------------------------------------------------------------- 1 | 多线程单例模式的实现代码 2 | -------------------------------------------------------------------------------- /src/singleton/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | CXXFLAGS += -std=c++11 4 | 5 | OBJS := main.o \ 6 | singleton.o \ 7 | 8 | $(TARGET): $(OBJS) 9 | $(CXX) $^ -o $@ 10 | 11 | clean: 12 | $(RM) $(OBJS) $(TARGET) 13 | -------------------------------------------------------------------------------- /src/singleton/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "singleton.h" 2 | 3 | int main(void) { 4 | Singleton *ton1 = Singleton::GetInstance(); 5 | Singleton *ton2 = Singleton::GetInstance(); 6 | 7 | if (ton1 == ton2) 8 | std::cout << "ton1 == ton2" << std::endl; 9 | 10 | std::cout << "ton1->var=" << ton1->getVar() << std::endl; 11 | std::cout << "ton2->var=" << ton2->getVar() << std::endl; 12 | 13 | ton1->setVar(150); 14 | 15 | std::cout << "ton1->var=" << ton1->getVar() << std::endl; 16 | std::cout << "ton2->var=" << ton2->getVar() << std::endl; 17 | 18 | Singleton::DelInstance(); //必须显式地删除 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/singleton/cpp/singleton.cc: -------------------------------------------------------------------------------- 1 | #include "singleton.h" 2 | 3 | Singleton* Singleton::_instance = 0; 4 | 5 | Singleton::Singleton() 6 | { 7 | this->var = 20; 8 | std::cout << "Singleton Constructor" << std::endl; 9 | } 10 | 11 | Singleton* Singleton::GetInstance() 12 | { 13 | if (0 == _instance) 14 | _instance = new Singleton(); 15 | return _instance; 16 | } 17 | 18 | // setter & getter 19 | int Singleton::getVar() 20 | { 21 | return this->var; 22 | } 23 | 24 | void Singleton::setVar(int var) 25 | { 26 | this->var = var; 27 | } 28 | 29 | Singleton::~Singleton() 30 | { 31 | std::cout << "Singleton Destructor" << std::endl; 32 | if (0 != _instance) { 33 | _instance->var = 0; 34 | _instance = 0; 35 | } 36 | } 37 | 38 | void Singleton::DelInstance() { 39 | delete _instance; 40 | } 41 | -------------------------------------------------------------------------------- /src/singleton/cpp/singleton.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 oxnz, All rights reserved 3 | */ 4 | 5 | #include 6 | 7 | class Singleton 8 | { 9 | public: 10 | static Singleton* GetInstance(); //工厂方法(用来获得实例) 11 | static void DelInstance(); 12 | int getVar(); 13 | void setVar(int); 14 | private: 15 | // private constructor, prevent clients from creating a new Singleton 16 | Singleton(); 17 | // prevent clients from copying a Singleton 18 | Singleton(const Singleton&) = delete; 19 | Singleton& operator=(const Singleton&) = delete; 20 | // prevent clients from deleting a Singleton 21 | virtual ~Singleton(); 22 | private: 23 | static Singleton* _instance; // the one and only instance 24 | int var; // member for test 25 | }; 26 | -------------------------------------------------------------------------------- /src/singleton/perl/Singleton.pm: -------------------------------------------------------------------------------- 1 | package Singleton; 2 | 3 | use strict; 4 | use warnings; 5 | use feature 'state'; 6 | use vars qw(@VERSION); 7 | 8 | @VERSION = 1.00; 9 | 10 | sub new { 11 | my ($class) = @_; 12 | state $instance; 13 | 14 | if (! defined $instance) { 15 | $instance = bless {}, $class; 16 | } 17 | return $instance; 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /src/singleton/perl/main.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # @author: 0xnz 3 | 4 | BEGIN { 5 | push (@INC, './'); 6 | } 7 | 8 | use strict; 9 | use warnings; 10 | -------------------------------------------------------------------------------- /src/singleton/python/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #coding: utf-8 3 | 4 | from singleton import A 5 | 6 | if __name__ == '__main__': 7 | a1 = A() 8 | a2 = A() 9 | assert(a1 == a2) 10 | assert(id(a1) == id(a2)) 11 | from copy import deepcopy 12 | a3 = deepcopy(a2) 13 | assert(a2 == a3) 14 | -------------------------------------------------------------------------------- /src/singleton/ruby/appconfig.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'singleton' 4 | 5 | class AppConfig 6 | include Singleton 7 | attr_accessor :data 8 | 9 | def version 10 | '1.0.0' 11 | end 12 | end 13 | 14 | p AppConfig.instance.data = {enabled: true} 15 | p AppConfig.instance.version 16 | 17 | second = AppConfig.instance 18 | p second.data = {enabled: false} 19 | p AppConfig.instance.data 20 | -------------------------------------------------------------------------------- /src/singleton/ruby/test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'singleton' 4 | 5 | class Example 6 | include Singleton 7 | attr_accessor :keep, :strip 8 | def _dump(depth) 9 | # this strips the @strip information from the instance 10 | Marshal.dump(@keep, depth) 11 | end 12 | 13 | def self._load(str) 14 | instance.keep = Marshal.load(str) 15 | instance 16 | end 17 | end 18 | 19 | a = Example.instance 20 | 21 | a.keep = "keep this" 22 | a.strip = "get rid of this" 23 | a.taint 24 | 25 | stored_state = Marshal.dump(a) 26 | 27 | a.keep = nil 28 | a.strip = nil 29 | b = Marshal.load(stored_state) 30 | p a == b # => true 31 | p a.keep # => "keep this" 32 | p a.strip # => nil 33 | -------------------------------------------------------------------------------- /src/state/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | state.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/state/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "state.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | State *pState = new InhaleState(); //初始状态 5 | Work *pWork = new Work(pState); 6 | 7 | for (int i = 1; i < 5; ++i) { 8 | pWork->SetStep(i); 9 | pWork->Operation(); //操作 10 | } 11 | 12 | delete pWork; 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/state/cpp/state.h: -------------------------------------------------------------------------------- 1 | #ifndef STATE_H 2 | #define STATE_H 3 | 4 | class Work; 5 | 6 | class State 7 | { 8 | public: 9 | virtual void Operation(Work*){} 10 | virtual ~State(); 11 | }; 12 | 13 | class ExhaustState : public State 14 | { 15 | public: 16 | void Operation(Work* w); 17 | }; 18 | 19 | class ActState : public State 20 | { 21 | public: 22 | void Operation(Work* w); 23 | }; 24 | 25 | class CompressState : public State 26 | { 27 | public: 28 | void Operation(Work* w); 29 | }; 30 | 31 | class InhaleState : public State 32 | { 33 | public: 34 | void Operation(Work* w); 35 | }; 36 | 37 | class Work 38 | { 39 | public: 40 | Work(State* state); 41 | int GetStep() const; 42 | void SetStep(int step); 43 | void SetState(State* state); 44 | void Operation(); 45 | ~Work(); 46 | private: 47 | State* m_pState; 48 | int m_nStep; 49 | }; 50 | 51 | #endif//STATE_H 52 | -------------------------------------------------------------------------------- /src/state/perl/Context.pm: -------------------------------------------------------------------------------- 1 | package Context; 2 | 3 | use strict; 4 | use warnings; 5 | use State::ConcreteStateA; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = { 10 | state => State::ConcreteStateA->instance, 11 | }; 12 | return bless $self, $class; 13 | } 14 | 15 | sub state { 16 | my ($self, $state) = @_; 17 | $self->{state} = $state if defined($state); 18 | return $self->{state}; 19 | } 20 | 21 | sub request { 22 | my ($self) = @_; 23 | $self->state->handle($self); 24 | } 25 | 26 | 1; 27 | -------------------------------------------------------------------------------- /src/state/perl/State.pm: -------------------------------------------------------------------------------- 1 | package State; 2 | 3 | use strict; 4 | use warnings; 5 | use feature 'state'; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = {}; 10 | return bless $self, $class; 11 | } 12 | 13 | sub instance { 14 | my $class = shift; 15 | return $class->new; 16 | } 17 | 18 | sub handle { 19 | die "INTERFACE METHOD HANDLE CANNOT BE CALLED DIRECTLY\n"; 20 | } 21 | 22 | 1; 23 | -------------------------------------------------------------------------------- /src/state/perl/State/ConcreteStateA.pm: -------------------------------------------------------------------------------- 1 | package State::ConcreteStateA; 2 | use parent State; 3 | 4 | use strict; 5 | use warnings; 6 | use State::ConcreteStateB; 7 | use Data::Dump; 8 | use feature 'state'; 9 | 10 | sub new { 11 | my ($class, $args) = @_; 12 | state $instance; 13 | if (! defined $instance) { 14 | $instance = $class->SUPER::new($args); 15 | } 16 | return $instance; 17 | } 18 | 19 | sub handle { 20 | my ($self, $context) = @_; 21 | print "ConcreteStateA handle method\n"; 22 | $context->state(State::ConcreteStateB->instance); 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /src/state/perl/State/ConcreteStateB.pm: -------------------------------------------------------------------------------- 1 | package State::ConcreteStateB; 2 | use parent State; 3 | 4 | use strict; 5 | use warnings; 6 | use State::ConcreteStateA; 7 | use Data::Dump; 8 | use feature 'state'; 9 | 10 | sub new { 11 | my ($class, $args) = @_; 12 | state $instance; 13 | if (! defined $instance) { 14 | $instance = $class->SUPER::new($args); 15 | } 16 | return $instance; 17 | } 18 | 19 | sub handle { 20 | my ($self, $context) = @_; 21 | print "ConcreteStateB handle method\n"; 22 | $context->state(State::ConcreteStateA->instance); 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /src/state/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use State::ConcreteStateA; 6 | use State::ConcreteStateB; 7 | use Context; 8 | 9 | my $context = Context->new; 10 | $context->request; 11 | $context->request; 12 | $context->request; 13 | $context = undef; 14 | -------------------------------------------------------------------------------- /src/state/php/client.php: -------------------------------------------------------------------------------- 1 | request(); 11 | $context->request(); 12 | $context->request(); 13 | $context = null; 14 | } 15 | } 16 | 17 | Client::main(); 18 | 19 | ?> 20 | -------------------------------------------------------------------------------- /src/state/php/context.php: -------------------------------------------------------------------------------- 1 | _state = ConcreteStateA::getInstance(); 12 | } 13 | 14 | public function setState(State $state) { 15 | $this->_state = $state; 16 | } 17 | 18 | public function request() { 19 | $this->_state->handle($this); 20 | } 21 | } 22 | 23 | ?> 24 | -------------------------------------------------------------------------------- /src/state/python/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | from work import Work 5 | 6 | if __name__ == "__main__": 7 | work = Work() 8 | work.setHour(8) 9 | work.operate() 10 | 11 | work.setHour(11) 12 | work.operate() 13 | 14 | work.setHour(14) 15 | work.operate() 16 | 17 | work.setHour(19) 18 | work.operate() 19 | -------------------------------------------------------------------------------- /src/state/python/work.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | 3 | from state import MorningState 4 | 5 | class Work: 6 | def __init__(self): 7 | self.__hour = 8 8 | self.__state = MorningState() 9 | 10 | def getHour(self): 11 | return self.__hour 12 | def setHour(self, h): 13 | self.__hour = h 14 | def setState(self, state): 15 | self.__state = state 16 | def operate(self): 17 | self.__state.operate(self) 18 | 19 | -------------------------------------------------------------------------------- /src/state/state.md: -------------------------------------------------------------------------------- 1 | #状态(State)模式 2 | 3 | 状态模式(State Pattern)是设计模式的一种,属于行为模式。 4 | 5 | >定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。 6 | 7 | 状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。 8 | 9 | >意图:允许一个对象在其内部状态改变时改变它的行为 10 | 11 | ##一. 举例 12 | 13 | 一般汽车发动机工作时有四种状态,吸气、压缩、做功和排气。 14 | 15 | 在运行时,不同的状态会有不同的行为,当前的状态机在适当的时候会过渡到下一状态。 16 | 17 | 其实用户在使用时根本不知道当前的状态,也无需知道当前的状态。用户只需要给发动机一个初始状态,最后得到一个停止状态就行了。 18 | 19 | ###结构图如下: 20 | ![结构图](./uml1.png) 21 | 22 | ###代码如下: 23 | 24 | ##二. 状态模式 25 | 26 | 定义:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 27 | 28 | ###结构图: 29 | ![结构图](./uml2.png) 30 | 31 | 32 | ###适用场景: 33 | 34 | 1. 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。(上面的例子就是这种情况) 35 | 2. 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。 -------------------------------------------------------------------------------- /src/state/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/state/uml1.png -------------------------------------------------------------------------------- /src/state/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/state/uml2.png -------------------------------------------------------------------------------- /src/strategy/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | 5 | $(TARGET): $(OBJS) 6 | $(CXX) $^ -o $@ 7 | 8 | clean: 9 | $(RM) $(OBJS) $(TARGET) 10 | -------------------------------------------------------------------------------- /src/strategy/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //策略类 4 | class Algorithm 5 | { 6 | public: 7 | virtual void calculate() = 0; 8 | virtual ~Algorithm(){} 9 | }; 10 | 11 | class RSA_Algorithm : public Algorithm 12 | { 13 | public: 14 | void calculate() { std::cout << "RSA" << std::endl; } 15 | }; 16 | 17 | class DES_Algorithm : public Algorithm 18 | { 19 | public: 20 | void calculate() { std::cout << "DES" << std::endl; } 21 | }; 22 | 23 | //策略上下文 24 | class Algorithm_Context 25 | { 26 | private: 27 | Algorithm *m_pAlgorithm; 28 | public: 29 | Algorithm_Context(Algorithm* a) : m_pAlgorithm(a) {} 30 | void calculate() { m_pAlgorithm->calculate(); } 31 | ~Algorithm_Context() { delete m_pAlgorithm; } 32 | }; 33 | 34 | int main() { 35 | Algorithm_Context context(new RSA_Algorithm()); //使用具体算法 36 | context.calculate(); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /src/strategy/perl/Algorithm.pm: -------------------------------------------------------------------------------- 1 | package Algorithm; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | my $self = {}; 9 | return bless $self, $class; 10 | } 11 | 12 | sub perform { 13 | die "INTERFACE METHOD PERFORM CANNOT BE CALLED DIRECTLY\n"; 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /src/strategy/perl/Algorithm/DES.pm: -------------------------------------------------------------------------------- 1 | package Algorithm::DES; 2 | use parent Algorithm; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | return $self; 11 | } 12 | 13 | sub perform { 14 | print "DES perform\n"; 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /src/strategy/perl/Algorithm/RSA.pm: -------------------------------------------------------------------------------- 1 | package Algorithm::RSA; 2 | use parent Algorithm; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = $class->SUPER::new($args); 10 | return $self; 11 | } 12 | 13 | sub perform { 14 | print "RSA perform\n"; 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /src/strategy/perl/Context.pm: -------------------------------------------------------------------------------- 1 | package Context; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $algorithm) = @_; 8 | my $self = { 9 | algorithm => $algorithm, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub perform { 15 | my $self = shift; 16 | $self->{algorithm}->perform; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /src/strategy/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use Context; 6 | use Algorithm::DES; 7 | use Algorithm::RSA; 8 | 9 | my $context = Context->new(Algorithm::RSA->new); 10 | $context->perform; 11 | -------------------------------------------------------------------------------- /src/strategy/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/strategy/uml1.png -------------------------------------------------------------------------------- /src/strategy/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/strategy/uml2.png -------------------------------------------------------------------------------- /src/template/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | class.o \ 5 | 6 | $(TARGET): $(OBJS) 7 | $(CXX) $^ -o $@ 8 | 9 | clean: 10 | $(RM) $(OBJS) $(TARGET) 11 | -------------------------------------------------------------------------------- /src/template/cpp/class.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "class.h" 3 | 4 | void AbstractClass::TemplateMethod() 5 | { 6 | PrimitiveOperation1(); 7 | PrimitiveOperation2(); 8 | } 9 | 10 | void ConcreteClass1::PrimitiveOperation1() 11 | { 12 | std::cout << "ConcreteClass1->PrimitiveOperation1" << std::endl; 13 | } 14 | 15 | void ConcreteClass1::PrimitiveOperation2() 16 | { 17 | std::cout << "ConcreteClass1->PrimitiveOperation2" << std::endl; 18 | } 19 | 20 | void ConcreteClass2::PrimitiveOperation1() 21 | { 22 | std::cout << "ConcreteClass2->PrimitiveOperation1" << std::endl; 23 | } 24 | 25 | void ConcreteClass2::PrimitiveOperation2() 26 | { 27 | std::cout << "ConcreteClass2->PrimitiveOperation2" << std::endl; 28 | } 29 | -------------------------------------------------------------------------------- /src/template/cpp/class.h: -------------------------------------------------------------------------------- 1 | #ifndef CLASS_H 2 | #define CLASS_H 3 | 4 | //抽象基类,实现了一个模板方法 5 | class AbstractClass 6 | { 7 | public: 8 | //模板方法,只在抽象基类中实现 9 | void TemplateMethod(); 10 | virtual ~AbstractClass(){} 11 | protected: 12 | virtual void PrimitiveOperation1() = 0; 13 | virtual void PrimitiveOperation2() = 0; 14 | AbstractClass(){} 15 | }; 16 | 17 | //具体子类,实现操作的特定细节 18 | class ConcreteClass1 : public AbstractClass 19 | { 20 | public: 21 | ConcreteClass1(){} 22 | ~ConcreteClass1(){} 23 | protected: 24 | void PrimitiveOperation1(); 25 | void PrimitiveOperation2(); 26 | }; 27 | 28 | //具体子类,实现操作的特定细节 29 | class ConcreteClass2 : public AbstractClass 30 | { 31 | public: 32 | ConcreteClass2(){} 33 | ~ConcreteClass2(){} 34 | protected: 35 | void PrimitiveOperation1(); 36 | void PrimitiveOperation2(); 37 | }; 38 | 39 | #endif//CLASS_H 40 | -------------------------------------------------------------------------------- /src/template/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include "class.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | AbstractClass* c1 = new ConcreteClass1(); 5 | AbstractClass* c2 = new ConcreteClass2(); 6 | 7 | c1->TemplateMethod(); 8 | c2->TemplateMethod(); 9 | 10 | delete c1; 11 | delete c2; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/template/perl/AbstractClass.pm: -------------------------------------------------------------------------------- 1 | package AbstractClass; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $args) = @_; 8 | return bless {}, $class; 9 | } 10 | 11 | sub templateMethod { 12 | my $self = shift; 13 | $self->primitiveOperation1; 14 | $self->primitiveOperation2; 15 | } 16 | 17 | sub primitiveOperation1 { 18 | die "ABSTRACT CLASS METHOD CANNOT BE CALLED DIRECTLY\n"; 19 | } 20 | 21 | sub primitiveOperation2 { 22 | die "ABSTRACT CLASS METHOD CANNOT BE CALLED DIRECTLY\n"; 23 | } 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /src/template/perl/AbstractClass/ConcreteClass.pm: -------------------------------------------------------------------------------- 1 | package AbstractClass::ConcreteClass; 2 | use parent AbstractClass; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $args) = @_; 9 | my $self = {}; 10 | return bless $self, $class; 11 | } 12 | 13 | sub primitiveOperation1 { 14 | print scalar((caller(0))[3]), "\n"; 15 | } 16 | 17 | sub primitiveOperation2 { 18 | print scalar((caller(0))[3]), "\n"; 19 | } 20 | 21 | 1; 22 | -------------------------------------------------------------------------------- /src/template/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # auther: oxnz 3 | # coding: utf-8 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use AbstractClass::ConcreteClass; 9 | 10 | my $cls = AbstractClass::ConcreteClass->new; 11 | $cls->templateMethod; 12 | -------------------------------------------------------------------------------- /src/template/template.md: -------------------------------------------------------------------------------- 1 | #模板(Template)模式 2 | 3 | ##一. 问题 4 | 在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,但是逻辑(算法)的框架(或通用的应用算法)是相同的。Template提供了这种情况的一个实现框架。 5 | 6 | ##二. 模式 7 | 8 | Template 模式是采用继承的方式实现这一点:将逻辑(算法)框架放在抽象基类中,并定义好细节的接口,子类中实现细节。 9 | ![模式](./uml.png) 10 | 11 | ##三. 代码 12 | 13 | 其关键点就是将通用算法封装在抽象基类中,并将不同的算法细节放到子类中实现。 14 | 15 | ##四. 应用场景: 16 | 17 | 1. 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。 18 | 2. 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。 -------------------------------------------------------------------------------- /src/template/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/template/uml.png -------------------------------------------------------------------------------- /src/test.perl.template: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # auther: oxnz 3 | # coding: utf-8 4 | 5 | use strict; 6 | use warnings; 7 | -------------------------------------------------------------------------------- /src/visitor/cpp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := test 2 | 3 | OBJS := main.o \ 4 | status.o \ 5 | seed.o \ 6 | 7 | $(TARGET): $(OBJS) 8 | $(CXX) $^ -o $@ 9 | 10 | clean: 11 | $(RM) $(OBJS) $(TARGET) 12 | -------------------------------------------------------------------------------- /src/visitor/cpp/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "seed.h" 3 | #include "status.h" 4 | 5 | //对象结构类,为了对比不同种子 6 | class ObjectStructure 7 | { 8 | private: 9 | std::list m_lSeed; 10 | public: 11 | void Attach(Seed* seed) 12 | { 13 | m_lSeed.push_back(seed); 14 | } 15 | 16 | void Detach(Seed* seed) 17 | { 18 | m_lSeed.remove(seed); 19 | } 20 | 21 | void Display(Status* status) 22 | { 23 | std::list::iterator it = m_lSeed.begin(); 24 | for (; it != m_lSeed.end(); ++it) { 25 | (*it)->Accept(status); 26 | } 27 | } 28 | }; 29 | 30 | int main(int argc, char *argv[]) { 31 | ObjectStructure obj; 32 | 33 | //加入要对比的两个种子 34 | obj.Attach(new Seed_A()); 35 | obj.Attach(new Seed_B()); 36 | 37 | //查看各种状态下两个种子的情况 38 | obj.Display(new Rain_Status()); 39 | obj.Display(new Sun_Status()); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /src/visitor/cpp/seed.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "seed.h" 3 | #include "status.h" 4 | 5 | void Seed_A::Accept(Status* status) 6 | { 7 | status->VisitSeed_A(this); 8 | } 9 | 10 | void Seed_B::Accept(Status* status) 11 | { 12 | status->VisitSeed_B(this); 13 | } 14 | -------------------------------------------------------------------------------- /src/visitor/cpp/seed.h: -------------------------------------------------------------------------------- 1 | #ifndef SEED_H 2 | #define SEED_H 3 | 4 | class Status; 5 | 6 | class Seed 7 | { 8 | public: 9 | virtual void Accept(Status* status) = 0; 10 | virtual ~Seed(){} 11 | protected: 12 | Seed(){} 13 | }; 14 | 15 | class Seed_A : public Seed 16 | { 17 | public: 18 | Seed_A(){} 19 | void Accept(Status* status); 20 | ~Seed_A(){} 21 | }; 22 | 23 | class Seed_B : public Seed 24 | { 25 | public: 26 | Seed_B(){} 27 | void Accept(Status* status); 28 | ~Seed_B(){} 29 | }; 30 | 31 | #endif//SEED_H 32 | -------------------------------------------------------------------------------- /src/visitor/cpp/status.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "seed.h" 3 | #include "status.h" 4 | 5 | void Rain_Status::VisitSeed_A(Seed* elm) 6 | { 7 | std::cout << "Rain will visit Seed A..." << std::endl; 8 | } 9 | 10 | void Rain_Status::VisitSeed_B(Seed* elm) 11 | { 12 | std::cout << "Rain will visit Seed B..." << std::endl; 13 | } 14 | 15 | void Sun_Status::VisitSeed_A(Seed* elm) 16 | { 17 | std::cout << "Sun will visit Seed A..." << std::endl; 18 | } 19 | 20 | void Sun_Status::VisitSeed_B(Seed* elm) 21 | { 22 | std::cout << "Sun will visit Seed B..." << std::endl; 23 | } 24 | -------------------------------------------------------------------------------- /src/visitor/cpp/status.h: -------------------------------------------------------------------------------- 1 | #ifndef STATUS_H 2 | #define STATUS_H 3 | 4 | class Seed; 5 | 6 | class Status 7 | { 8 | public: 9 | virtual void VisitSeed_A(Seed* elm){} 10 | virtual void VisitSeed_B(Seed* elm){} 11 | virtual ~Status(){} 12 | protected: 13 | Status(){} 14 | }; 15 | 16 | class Rain_Status : public Status 17 | { 18 | public: 19 | Rain_Status(){} 20 | virtual ~Rain_Status(){} 21 | virtual void VisitSeed_A(Seed* elm); 22 | virtual void VisitSeed_B(Seed* elm); 23 | }; 24 | 25 | class Sun_Status : public Status 26 | { 27 | public: 28 | Sun_Status(){} 29 | virtual ~Sun_Status(){} 30 | virtual void VisitSeed_A(Seed* elm); 31 | virtual void VisitSeed_B(Seed* elm); 32 | }; 33 | 34 | #endif//STATUS_H 35 | -------------------------------------------------------------------------------- /src/visitor/perl/Corporation.pm: -------------------------------------------------------------------------------- 1 | package Corporation; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $name) = @_; 8 | my $self = { 9 | name => $name, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub name { 15 | my ($self, $name) = @_; 16 | $self->{name} = $name if defined($name); 17 | return $self->{name}; 18 | } 19 | 20 | sub accept { 21 | die "INTERFACE METHOD ACCEPT CANNOT BE CALLED DIRECTLY\n"; 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /src/visitor/perl/Corporation/CorporationA.pm: -------------------------------------------------------------------------------- 1 | package Corporation::CorporationA; 2 | use parent Corporation; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $name) = @_; 9 | my $self = $class->SUPER::new($name); 10 | return $self; 11 | } 12 | 13 | sub accept { 14 | my ($self, $visitor) = @_; 15 | print "Corporation ", $self->name, " accepting visitor ", $visitor->name, 16 | "\n"; 17 | $visitor->visit($self); 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /src/visitor/perl/Corporation/CorporationB.pm: -------------------------------------------------------------------------------- 1 | package Corporation::CorporationB; 2 | use parent Corporation; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $name) = @_; 9 | my $self = $class->SUPER::new($name); 10 | return $self; 11 | } 12 | 13 | sub accept { 14 | my ($self, $visitor) = @_; 15 | print "Corporation ", $self->name, " accepting visitor ", $visitor->name, 16 | "\n"; 17 | $visitor->visit($self); 18 | } 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /src/visitor/perl/Visitor.pm: -------------------------------------------------------------------------------- 1 | package Visitor; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub new { 7 | my ($class, $name) = @_; 8 | my $self = { 9 | name => $name, 10 | }; 11 | return bless $self, $class; 12 | } 13 | 14 | sub name { 15 | my ($self, $name) = @_; 16 | $self->{name} = $name if defined($name); 17 | return $self->{name}; 18 | } 19 | 20 | sub visit { 21 | die "INTERFACE METHOD VISIT CANNOT BE CALLED DIRECTLY\n"; 22 | } 23 | 24 | 1; 25 | -------------------------------------------------------------------------------- /src/visitor/perl/Visitor/VisitorA.pm: -------------------------------------------------------------------------------- 1 | package Visitor::VisitorA; 2 | use parent Visitor; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $name) = @_; 9 | my $self = $class->SUPER::new($name); 10 | return $self; 11 | } 12 | 13 | sub visit { 14 | my ($self, $corporation) = @_; 15 | print "Visitor ", $self->name, "is visiting corporation ", 16 | $corporation->name, "\n"; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /src/visitor/perl/Visitor/VisitorB.pm: -------------------------------------------------------------------------------- 1 | package Visitor::VisitorB; 2 | use parent Visitor; 3 | 4 | use strict; 5 | use warnings; 6 | 7 | sub new { 8 | my ($class, $name) = @_; 9 | my $self = $class->SUPER::new($name); 10 | return $self; 11 | } 12 | 13 | sub visit { 14 | my ($self, $corporation) = @_; 15 | print "Visitor ", $self->name, "is visiting corporation ", 16 | $corporation->name, "\n"; 17 | } 18 | 19 | 1; 20 | -------------------------------------------------------------------------------- /src/visitor/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use Data::Dump; 6 | use Corporation::CorporationA; 7 | use Corporation::CorporationB; 8 | use Visitor::VisitorA; 9 | use Visitor::VisitorB; 10 | 11 | my @visitors = ( 12 | Visitor::VisitorA->new("Alex"), 13 | Visitor::VisitorB->new("John"), 14 | ); 15 | my @corporations = ( 16 | Corporation::CorporationA->new("Intel"), 17 | Corporation::CorporationB->new("AMD"), 18 | ); 19 | 20 | foreach my $visitor (@visitors) { 21 | foreach my $corporation (@corporations) { 22 | $corporation->accept($visitor); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/visitor/uml1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/visitor/uml1.png -------------------------------------------------------------------------------- /src/visitor/uml2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxnz/design-patterns/6fe3b4e7a2f524a5c1ebac7f4d3eed0b0f955c59/src/visitor/uml2.png -------------------------------------------------------------------------------- /src/visitor/visitor.md: -------------------------------------------------------------------------------- 1 | #访问者(Visitor)模式 2 | 3 | 一. 访问者模式 4 | 5 | 定义:表示一个作用于某对象结构中的各元素的操作。它你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 6 | 7 | 结构如下: 8 | ![结构](./uml1.png) 9 | 10 | 二. 举例 11 | 12 | 假设有一项科学实验,是用来对比两种种子在不同环境下的生长情况。 13 | 14 | 两种种子,一种是普通的种子(Seed_A),一种是太空运回的种子(Seed_B)。 15 | 16 | 生长环境,分别是在多雨环境下(Rain_Status),阳光环境下(Sun_Status)等等。 17 | 18 | 结构如下: 19 | ![结构](./uml2.png) 20 | 21 | 三. 说明 22 | 23 | 1. 首先有一点要明确,就是两种种子不会轻易改变,也就是只有普通和太空种子两种。换句话说就是,数据结构比较稳定。 24 | 25 | 2. 可以变的是新增的状态,比如增加一个X光下的生成情况,等等。说白了就是,操作集合可以相对自由的演化。 26 | 27 | 3. 这种结构的优点是,增加新的操作很容易;缺点是,增加新的数据结构有点困难,因为你要在每一个访问者里都添加相应的操作。 28 | 29 | 4. 种子生长图相对于访问者模式的结构图有如下关系: 30 | 31 | seed(种子)相当于 element(元素),这个是不怎么变的。 32 | status(状态) 相当于 visitor(访问者),这个是可变且易变的。要注意的是,每个访问者都要对所有的元素(element)进行操作。 33 | 34 | 5. 事实上我们很少用这种模式,因为数据结构(element)不变的情况很少。 --------------------------------------------------------------------------------