Dahua design pattern source code

Posted by pelleas on Mon, 29 Nov 2021 17:45:23 +0100

(1) Simple factory mode

Mainly used to create objects. Adding a new class will not affect the previous system code. The core idea is to use a factory to generate different classes according to the input conditions, and then get different results according to the virtual functions of different classes.

GOOD: applicable to different situations when creating different classes

BUG: the client must know the base class and factory class, and the coupling is poor

(factory class and base class are related)

Example:

//Base class
class COperation
{
public:
	int m_nFirst;
	int m_nSecond;
	virtual double GetResult()
	{
		double dResult=0;
		return dResult;
	}
};
//addition
class AddOperation : public COperation
{
public:
	virtual double GetResult()
	{
		return m_nFirst+m_nSecond;
	}
};
//subtraction
class SubOperation : public COperation
{
public:
	virtual double GetResult()
	{
		return m_nFirst-m_nSecond;
	}
};

//Factory class
class CCalculatorFactory
{
public:
	static COperation* Create(char cOperator);
};

COperation* CCalculatorFactory::Create(char cOperator)
{
	COperation *oper;
    //In C #, you can use reflection to cancel the switch used in judgment. What is used in C + +? RTTI??
	switch (cOperator)
	{
	case '+':
		oper=new AddOperation();
		break;
	case '-':
		oper=new SubOperation();
		break;
	default:
		oper=new AddOperation();
		break;
	}
	return oper;
}

client

int main()
{
	int a,b;
	cin>>a>>b;
	COperation * op=CCalculatorFactory::Create('-');
	op->m_nFirst=a;
	op->m_nSecond=b;
	cout<<op->GetResult()<<endl;
	return 0;
}

(2) Strategy mode

Define algorithm families and package them separately, so that they can be replaced with each other, so that algorithm changes will not affect users

GOOD: the members in the class are mainly methods, and the algorithm changes frequently; It simplifies unit testing (because each algorithm has its own class and can be tested separately through its own interface).

The policy mode is basically the same as the simple factory mode, but the simple factory mode can only solve the problem of object creation. The policy mode should be used for frequently changing algorithms.

BUG: the client needs to make a judgment

  example

//Policy base class
class COperation
{
public:
	int m_nFirst;
	int m_nSecond;
	virtual double GetResult()
	{
		double dResult=0;
		return dResult;
	}
};

//Policy concrete class - addition class
class AddOperation : public COperation
{
public:
	AddOperation(int a,int b)
	{
		m_nFirst=a;
		m_nSecond=b;
	}
	virtual double GetResult()
	{
		return m_nFirst+m_nSecond;
	}
};

class Context
{
private:
	COperation* op;
public:
    Context(COperation* temp)
	{
        op=temp;
	}
	double GetResult()
	{
		return op->GetResult();
	}
};

//client
int main()
{
	int a,b;
    char c;
	cin>>a>>b;
  cout<<"Please enter operator:;
    cin>>c;
    switch(c)
{
   case '+':
	    Context *context=new Context(new AddOperation(a,b));
	cout<<context->GetResult()<<endl;
    break;
   default:
    break;
}
	return 0;
}

Combination of strategy and factory

GOOD: the client only needs to access the Context class without knowing any other class information, realizing low coupling.

On the basis of the above example, modify the following contents

class Context
{
private:
	COperation* op;
public:
    Context(char cType)
	{
        switch (cType)
        {
		case '+':
			op=new AddOperation(3,8);
			break;
		default:
			op=new AddOperation();
			break;
        }
	}
	double GetResult()
	{
		return op->GetResult();
	}
};
//client
int main()
{
	int a,b;
	cin>>a>>b;
	Context *test=new Context('+');
	cout<<test->GetResult()<<endl;
	return 0;
}

Single responsibility principle

As far as a class is concerned, there should be only one reason for its change.

If a class undertakes too many responsibilities, it is equivalent to coupling these responsibilities together. The change of one responsibility may weaken or inhibit the class's ability to complete other responsibilities. This coupling will lead to fragile design. When changes occur, the design will suffer unexpected damage.

If you can think of more than one motivation to change a class, the class has more than one responsibility.

Open closed principle

Software entities can be extended, but cannot be modified. That is, they are open to expansion and closed to modification. In the face of requirements, the changes to the program are completed by adding code, rather than changing the existing code.

When changes occur, we create abstractions to isolate similar changes in the future.

The open closed principle is the core of object-oriented. Developers should abstract the frequently changing part of the program, and refuse to deliberately abstract and immature abstraction of any part.

Richter substitution principle

If a software entity uses a parent class, it must apply to its child classes. Moreover, it cannot detect the difference between parent objects and child objects. That is, in software, if the parent class is replaced with a child class, the behavior of the program does not change.

Subtypes must be able to replace their parent type.

Dependence Inversion Principle

Abstraction should not depend on details, and details should depend on abstraction, that is, programming for interfaces, not for implementations.

High level modules cannot rely on low-level modules, and both should rely on abstraction.

The dependency inversion principle is an object-oriented sign. It doesn't matter which language to write the program. If you consider how to program for abstract rather than details, that is, all dependencies of the program terminate in abstract classes or interfaces, that is, object-oriented design, and vice versa, procedural design.

(3) Decoration mode

Dynamically add some additional responsibilities to an object (unimportant functions are only performed occasionally). In terms of adding functions, the decoration mode is more flexible than generating subclasses. The construction process is unstable and controlled in series in the correct order.

GOOD: when you add new code to an old class, you usually add core responsibilities or main behaviors. When you need to add only specific functions that will be executed under specific circumstances (simply not the functions of the core application) Decoration mode is to put the additional functions to be added in separate classes, and let this class contain the objects to be decorated. When it needs to be executed, the client can selectively and sequentially wrap the objects with decoration functions.

example

#include <string>
#include <iostream>
using namespace std;
//people
class Person
{
private:
	string m_strName;
public:
	Person(string strName)
	{
		m_strName=strName;
	}
	Person(){}
	virtual void Show()
	{
		cout<<"Dressed up as:"<<m_strName<<endl;
	}

};
//Decoration class
class Finery :public Person
{
protected:
	Person* m_component;
public:
	void Decorate(Person* component)
	{
		m_component=component;
	}
	virtual void Show()
	{
		   m_component->Show();
	}
};
//T-shirt
class TShirts: public Finery
{
public:
	virtual void Show()
	{
		cout<<"T Shirts"<<endl;
		m_component->Show();
	}
};
//trousers
class BigTrouser :public  Finery
{
public:
	virtual void Show()
	{
		cout<<" Big Trouser"<<endl;
		m_component->Show();
	}
};

//client
int main()
{
	Person *p=new Person("petty thief");
	BigTrouser *bt=new BigTrouser();
	TShirts *ts=new TShirts();

	bt->Decorate(p);
	ts->Decorate(bt);
	ts->Show();
	return 0;
}

(4) Agent mode

GOOD: remote proxy can hide the fact that an object is in different address spaces

Virtual proxy: use proxy to store objects that need to be instantiated for a long time

Security proxy: used to control the access rights of real objects

Smart reference: when a real object is called, the proxy handles something else

Example:

#include <string>
#include <iostream>
using namespace std;
//Define interface
class Interface
{
public:
	virtual void Request()=0;
};
//Real class
class RealClass : public Interface
{
public:
	virtual void Request()
	{
		cout<<"Real request"<<endl;
	}
};
//proxy class
class ProxyClass : public Interface
{
private:
	RealClass* m_realClass;
public:
	virtual void Request()
	{
	    m_realClass= new RealClass();
		m_realClass->Request();
		delete m_realClass;
	}
};

  client:

int main()
{
	ProxyClass* test=new ProxyClass();
	test->Request();
	return 0;
}

(5) Factory method model

GOOD: fixed that the simple factory mode does not comply with the open closed principle. The factory method mode moves the selection judgment to the client for implementation. If you want to add new functions, you don't need to modify the original class, you can directly modify the client.

  Example:

#include <string>
#include <iostream>
using namespace std;
//Instance base class, equivalent to product (no abstraction for convenience)
class LeiFeng
{
public:
	virtual void Sweep()
	{
		cout<<"Lei Feng sweeps the floor"<<endl;
	}
};

//A college student learning from Lei Feng is equivalent to concrete product
class Student: public LeiFeng
{
public:
	virtual void Sweep()
	{
		cout<<"College students sweep the floor"<<endl;
	}
};

//Volunteers who learn from Lei Feng are equivalent to concrete product
class Volenter: public LeiFeng
{
public :
	virtual void Sweep()
	{
		cout<<"volunteer"<<endl;
	}
};
//Workshop base Creator
class LeiFengFactory
{
public:
	virtual LeiFeng* CreateLeiFeng()
	{
		return new LeiFeng();
	}
};
//Workshop specific category
class StudentFactory : public LeiFengFactory
{
public :
	virtual LeiFeng* CreateLeiFeng()
	{
		return new Student();
	}
};
class VolenterFactory : public LeiFengFactory
{
public:
	virtual LeiFeng* CreateLeiFeng()
	{
		return new Volenter();
	}
};
//client
int main()
{
	LeiFengFactory *sf=new LeiFengFactory();
	LeiFeng *s=sf->CreateLeiFeng();
	s->Sweep();
	delete s;
	delete sf;
	return 0;
}

(6) Prototype mode

GOOD: create another customizable object from one object without knowing any creation details. It can improve the creation performance. To put it bluntly, COPY an object completely.

Example:  

#include<iostream>
#include <vector>
#include <string>
using namespace std;

class Prototype //Abstract base class 
{ 
private:
	string m_strName;
public: 
	Prototype(string strName){ m_strName = strName; }
	Prototype() { m_strName = " "; }
	void Show() 
	{
		cout<<m_strName<<endl;
	}
	virtual Prototype* Clone() = 0 ; 
} ; 

// class ConcretePrototype1 
class ConcretePrototype1 : public Prototype 
{ 
public: 
	ConcretePrototype1(string strName) : Prototype(strName){}
	ConcretePrototype1(){}

	virtual Prototype* Clone() 
	{ 
		ConcretePrototype1 *p = new ConcretePrototype1() ; 
		*p = *this ; //copy object 
		return p ; 
	} 
} ; 

// class ConcretePrototype2 
class ConcretePrototype2 : public Prototype 
{ 
public: 
	ConcretePrototype2(string strName) : Prototype(strName){}
	ConcretePrototype2(){}

	virtual Prototype* Clone() 
	{ 
		ConcretePrototype2 *p = new ConcretePrototype2() ; 
		*p = *this ; //copy object 
		return p ; 
	} 
} ; 

//client
int main()
{
	ConcretePrototype1* test = new ConcretePrototype1("Xiao Wang");
	ConcretePrototype2* test2 = (ConcretePrototype2*)test->Clone();
	test->Show();
	test2->Show();
	return 0;
}

(7) Template method pattern

GOOD: transfer the unchanged code parts to the parent class, and leave the variable code in virtual for subclass rewriting

  Example:

#include<iostream>
#include <vector>
#include <string>
using namespace std;

class AbstractClass
{
public:
	void Show()
	{
		cout<<"I am"<<GetName()<<endl;
	}
protected:
	virtual string GetName()=0;
};

class Naruto : public AbstractClass
{
protected:
	virtual string GetName()
	{
		return "The most handsome six generations in the history of Huoying---set the Thames a great coup naruto";
	}
};

class OnePice : public AbstractClass
{
protected:
	virtual string GetName()
	{
		return "I'm a big pirate who does all kinds of evil---Monkey D Luffy";
	}
};

//client
int main()
{
	Naruto* man = new Naruto();
	man->Show();

	OnePice* man2 = new OnePice();
	man2->Show();

	return 0;
}

Dimitt's law

If two classes do not communicate directly, the two classes should not interact directly. If a class needs to call a method of another class, it can forward the call through the third class.

In the structural design of classes, each class should minimize the access rights of members.

           This rule is strongly reflected in the later adapter mode and interpretation mode.

(8) Appearance mode

GOOD: provide a consistent interface for a group of interfaces of the subsystem, making it more convenient for users to use.

  Example:

#include<iostream>
#include <string>
using namespace std;

class SubSysOne
{
public:
	void MethodOne()
	{
		cout<<"Method 1"<<endl;
	}
};

class SubSysTwo
{
public:
	void MethodTwo()
	{
		cout<<"Method 2"<<endl;
	}
};

class SubSysThree
{
public:
	void MethodThree()
	{
		cout<<"Method 3"<<endl;
	}
};

//Appearance class
class Facade
{
private:
	SubSysOne* sub1;
	SubSysTwo* sub2;
	SubSysThree* sub3;
public:
	Facade()
	{
		sub1 = new SubSysOne();
		sub2 = new SubSysTwo();
		sub3 = new SubSysThree();
	}
	~Facade()
	{
		delete sub1;
		delete sub2;
		delete sub3;
	}

	void FacadeMethod()
	{
		sub1->MethodOne();
		sub2->MethodTwo();
		sub3->MethodThree();
	}
};

//client
int main()
{
	Facade* test = new Facade();
	test->FacadeMethod();
	return 0;
}

(9) Builder mode (generator mode)

GOOD: applicable when the algorithm for creating complex objects should be independent of the components of the object and how they are assembled.  

  Example:

#include <string>
#include <iostream>
#include <vector>
using namespace std;

//Final product category
class Product 
{
private:
	vector<string> m_product;
public:
	void Add(string strtemp)
	{
		m_product.push_back(strtemp);
	}
	void Show()
	{
		vector<string>::iterator p=m_product.begin();
		while (p!=m_product.end())
		{
			cout<<*p<<endl;
			p++;
		}
	}
};

//Builder base class
class Builder
{
public:
	virtual void BuilderA()=0;
	virtual void BuilderB()=0;
	virtual Product* GetResult()=0;
};
//The first construction method
class ConcreteBuilder1 : public Builder
{
private:
	Product* m_product;
public:
	ConcreteBuilder1()
	{
		m_product=new Product();
	}
	virtual void BuilderA()
	{
		m_product->Add("one");
	}
	virtual void BuilderB()
	{
		m_product->Add("two");
	}
	virtual Product* GetResult()
	{
		return m_product;
	}
};
//The second construction method
class ConcreteBuilder2 : public Builder
{
private:
	Product * m_product;
public:
	ConcreteBuilder2()
	{
		m_product=new Product();
	}
	virtual void BuilderA()
	{
		m_product->Add("A");
	}
	virtual void BuilderB()
	{
		m_product->Add("B");
	}
	virtual Product* GetResult()
	{
		return m_product;
	}
};

//Conductor class
class Direct
{
public:
	void Construct(Builder* temp)
	{
		temp->BuilderA();
		temp->BuilderB();
	}
};

//client
int main()
{
	Direct *p=new Direct();
	Builder* b1=new ConcreteBuilder1();
	Builder* b2=new ConcreteBuilder2();

	p->Construct(b1);     //Call the first method
	Product* pb1=b1->GetResult();
	pb1->Show();

	p->Construct(b2);          //Call the second method
	Product * pb2=b2->GetResult();
	pb2->Show();
	return 0;
}

Example 2 (in fact, this example should be mentioned earlier):
#include <string>
#include <iostream>
#include <vector>
using namespace std;

class Person
{
public:
	virtual void CreateHead()=0;
	virtual void CreateHand()=0;
	virtual void CreateBody()=0;
	virtual void CreateFoot()=0;
};
class ThinPerson : public Person
{
public:
	virtual void CreateHead()
	{
		cout<<"thin head"<<endl;
	}
	virtual void CreateHand()
	{
		cout<<"thin hand"<<endl;
	}
	virtual void CreateBody()
	{
		cout<<"thin body"<<endl;
	}
	virtual void CreateFoot()
	{
		cout<<"thin foot"<<endl;
	}
};

class ThickPerson : public Person
{
public:
	virtual void CreateHead()
	{
		cout<<"ThickPerson head"<<endl;
	}
	virtual void CreateHand()
	{
		cout<<"ThickPerson hand"<<endl;
	}
	virtual void CreateBody()
	{
		cout<<"ThickPerson body"<<endl;
	}
	virtual void CreateFoot()
	{
		cout<<"ThickPerson foot"<<endl;
	}
};
//Conductor class
class Direct
{
private:
	Person* p;
public:
	Direct(Person* temp) { p = temp;}
	void Create()
	{
		p->CreateHead();
		p->CreateBody();
		p->CreateHand();
		p->CreateFoot();
	}
};

//Client code:
int main()
{
    Person *p=new ThickPerson();
	Direct *d= new Direct(p);
	d->Create();
	delete d;
	delete p;
	return 0;
}

(10) Observer mode

GOOD: defines a one to many relationship, which allows multiple observers (company employees) to listen to a subject object (secretary) at the same time. When the status of the subject object changes, all observers will be notified so that they can update themselves.

   Example:

#include <string>
#include <iostream>
#include <vector>
using namespace std;

class Secretary;
//Colleagues looking at stocks (observers, observers)
class StockObserver
{
private:
	string name;
	Secretary* sub;
public:
	StockObserver(string strname,Secretary* strsub)
	{
		name=strname;
		sub=strsub;
	}
	void Update();
};
//Secretary (subject object, notifier)
class Secretary
{
private:
	vector<StockObserver> observers;
public:
	string action;
	void Add(StockObserver ob)
	{
		observers.push_back(ob);
	}
	void Notify()
	{
        vector<StockObserver>::iterator p = observers.begin();
		while (p!=observers.end())
		{
			(*p).Update();
			p++;
		}
	}
};

void StockObserver::Update()
{
	cout<<name<<":"<<sub->action<<",Stop playing with stocks and start working"<<endl;
}

//client
int main()
{
    Secretary *p=new Secretary();  //Create Notifier

	//Observer
	StockObserver *s1= new StockObserver("petty thief",p);
	StockObserver *s2 = new StockObserver("Xiao Zhao",p);
    //Join notification queue
	p->Add(*s1);
	p->Add(*s2);
    //event
	p->action="Here comes the boss";
	//notice
	p->Notify();
	return 0;
}

Example:

#include <string>
#include <iostream>
#include <vector>
using namespace std;

class SecretaryBase;
//Abstract observer
class CObserverBase
{
protected:
	string name;
	SecretaryBase* sub;
public:
	CObserverBase(string strname,SecretaryBase* strsub)
	{
		name=strname;
		sub=strsub;
	}
	virtual void Update()=0;
};
//Specific observers look at the stock market
class StockObserver : public CObserverBase
{
public:
	StockObserver(string strname,SecretaryBase* strsub) : CObserverBase(strname,strsub)
	{
	}
	virtual void Update();
};

//Specific observers, look at the NBA
class NBAObserver : public CObserverBase
{
public:
	NBAObserver(string strname,SecretaryBase* strsub) : CObserverBase(strname,strsub){}
	virtual void Update();
};


//Abstract Notifier
class SecretaryBase
{
public:
	string action;
	vector<CObserverBase*> observers;
public:
	virtual void Attach(CObserverBase* observer)=0;
	virtual void Notify()=0;
};

//Specific Notifier
class Secretary :public SecretaryBase
{
public:
	void Attach(CObserverBase* ob)
	{
		observers.push_back(ob);
	}
	void Notify()
	{
        vector<CObserverBase*>::iterator p = observers.begin();
		while (p!=observers.end())
		{
			(*p)->Update();
			p++;
		}
	}
};

void StockObserver::Update()
{
	cout<<name<<":"<<sub->action<<",Stop playing with stocks and start working"<<endl;
}
void NBAObserver::Update()
{
	cout<<name<<":"<<sub->action<<",Don't look NBA Yes, the boss is here"<<endl;
}

  client:

int main()
{
    SecretaryBase *p=new Secretary();  //Create observer
	
	//Observed object
	CObserverBase *s1= new NBAObserver("petty thief",p);
	CObserverBase *s2 = new StockObserver("Xiao Zhao",p);
    //Join the observation queue
	p->Attach(s1);
	p->Attach(s2);
    //event
	p->action="Here comes the boss";
	//notice
	p->Notify();

	return 0;
}

(11) Abstract factory pattern

GOOD: defines an interface that creates a series of related or interdependent interfaces without specifying their specific classes.

Used to exchange product series, such as access - > sql server;

The specific class name of the product is separated by the implementation of the specific factory

  Example:

#include <string>
#include <iostream>
#include <vector>
using namespace std;

//User abstract interface
class IUser
{
public :
	virtual void GetUser()=0;
	virtual void InsertUser()=0;
};

//Department abstract interface
class IDepartment
{
public:
	virtual void GetDepartment()=0;
	virtual void InsertDepartment()=0;
};

//ACCESS user
class CAccessUser : public IUser
{
public:
	virtual void GetUser()
	{
		cout<<"Access GetUser"<<endl;
	}
	virtual void InsertUser()
	{
		cout<<"Access InsertUser"<<endl;
	}
};

//ACCESS Department
class CAccessDepartment : public IDepartment
{
public:
	virtual void GetDepartment()
	{
		cout<<"Access GetDepartment"<<endl;
	}
	virtual void InsertDepartment()
	{
		cout<<"Access InsertDepartment"<<endl;
	}
};

//SQL user
class CSqlUser : public IUser
{
public:
	virtual void GetUser()
	{
		cout<<"Sql User"<<endl;
	}
	virtual void InsertUser()
	{
		cout<<"Sql User"<<endl;
	}
};

//SQL department class
class CSqlDepartment: public IDepartment
{
public:
	virtual void GetDepartment()
	{
		cout<<"sql getDepartment"<<endl;
	}
	virtual void InsertDepartment()
	{
		cout<<"sql insertdepartment"<<endl;
	}
};

//Abstract factory
class IFactory
{
public:
	virtual IUser* CreateUser()=0;
	virtual IDepartment* CreateDepartment()=0;
};

//ACCESS factory
class AccessFactory : public IFactory
{
public:
	virtual IUser* CreateUser()
	{
		return new  CAccessUser();
	}
	virtual IDepartment* CreateDepartment()
	{
		return new CAccessDepartment();
	}
};

//SQL factory
class SqlFactory : public IFactory
{
public:
	virtual IUser* CreateUser()
	{
		return new  CSqlUser();
	}

	virtual IDepartment* CreateDepartment()
	{
		return new CSqlDepartment();
	}
};

client:

int main()
{
	IFactory* factory= new SqlFactory();
	IUser* user=factory->CreateUser();
	IDepartment* depart = factory->CreateDepartment();
	user->GetUser();
	depart->GetDepartment();
	return 0;
}

(12) State mode

GOOD: when the behavior of an object depends on its state and it must change its behavior according to the state at runtime, the state mode can be considered.

  example

#include <iostream>
using namespace std;

class Work;
class ForenoonState;
class NoonState;

class State
{
public:
	virtual void WriteProgram(Work* w)=0;
};

class Work
{
private:
	State* current;
public:
	double hour;
public:
	Work();
	void SetState(State* temp)
	{
       current =temp;
	}
	void Writeprogram()
	{
		current->WriteProgram(this);
	}

};

class NoonState :public State
{
public:
	virtual void WriteProgram(Work* w)
	{
		cout<<"execute"<<endl;
		if((w->hour)<13)
			cout<<"Not bad"<<endl;
		else
			cout<<"No, I'd better go to bed"<<endl;
	}
};

class ForenoonState : public State
{
public:
	virtual void WriteProgram(Work* w)
	{
		if((w->hour)<12)
			cout<<"Now the spirit is invincible"<<endl;
		else
		{
			w->SetState(new NoonState());
			w->Writeprogram(); //Pay attention to adding this sentence
		}
	}
};


Work::Work()
{
		current = new ForenoonState();
}

client:

int main()
{
	Work* mywork=new Work();
	mywork->hour=9;
	mywork->Writeprogram();
	mywork->hour = 14;
	mywork->Writeprogram();
	return 0;
}

(13) Adapter mode

GOOD: when both sides are not suitable for modification, you can consider using the adapter mode

Example:

#include <iostream>
using namespace std;

class Target
{
public:
	virtual void Request()
	{
		cout<<"Ordinary request"<<endl;
	}
};

class Adaptee
{
public:
	void SpecificalRequest()
	{
		cout<<"Special request"<<endl;
	}
};

class Adapter :public  Target
{
private:
	Adaptee* ada;
public:
	virtual void Request()
	{
		ada->SpecificalRequest();
		Target::Request();
	}
	Adapter()
	{
		ada=new Adaptee();
	}
	~Adapter()
	{
		delete ada;
	}
};

  client:

int main()
{
	Adapter * ada=new Adapter();
	ada->Request();
	delete ada;
	return 0;
}

Example 2

#include <iostream>
#include <string>
using namespace std;

class Player
{
protected:
	string name;
public:
	Player(string strName) { name = strName; }
	virtual void Attack()=0;
	virtual void Defense()=0;
};

class Forwards : public Player
{
public:
	Forwards(string strName):Player(strName){}
public:
	virtual void Attack()
	{
		cout<<name<<"Forward attack"<<endl;
	}
	virtual void Defense()
	{
		cout<<name<<"Forward defense"<<endl;
	}
};

class Center : public Player
{
public:
	Center(string strName):Player(strName){}
public:
	virtual void Attack()
	{
		cout<<name<<"Midfield attack"<<endl;
	}
	virtual void Defense()
	{
	    cout<<name<<"Defensive midfielder "<<endl;
	}
};

//Translation for midfield
class TransLater: public Player
{
private:
	Center *player;
public:
	TransLater(string strName):Player(strName)
	{
		player = new Center(strName);
	}
	virtual void Attack()
	{
		player->Attack();
	}
	virtual void Defense()
	{
		player->Defense();
	}
};

client

int main()
{
	Player *p=new TransLater("petty thief");
	p->Attack();
	return 0;
}

(14) Memo mode

GOOD: on the premise of not destroying encapsulation, capture the internal state of an object and save the state outside the object, so that the later object state can be restored to the previously saved state.

It is applicable to classes with complex functions but need to record or maintain attribute history; Or when the attributes to be saved are only a small part of many attributes, the Originator can restore to the previous state according to the saved Memo.

Example:

#include <iostream>
#include <string>
using namespace std;

class Memo;

//Initiate human
class Originator
{
public:
	string state;
    Memo* CreateMemo();
	void SetMemo(Memo* memo);
	void Show()
	{
		cout<<"Status:"<<state<<endl;
	}
};
//Memo class
class Memo
{
public:
	string state;
	Memo(string strState)
	{
		state= strState;
	}
};

Memo* Originator::CreateMemo()
{
	return new Memo(state);
}

void Originator::SetMemo(Memo* memo)
{
	state = memo->state;
}

//Manager class
class Caretaker
{
public:
	Memo* memo;
};

client:

int main()
{
	Originator* on=new Originator();
	on->state = "on";
	on->Show();

	Caretaker* c= new Caretaker();
	c->memo = on->CreateMemo();

	on->state = "off";
	on->Show();

	on->SetMemo(c->memo);
	on->Show();
	return 0;
}

(15) Combination mode

GOOD: the whole and part can be treated consistently (for example, copying a text, a paragraph of text and an article in WORD are the same operation)

  Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Component
{
public:
	string m_strName;
	Component(string strName)
	{
		m_strName = strName;
	}
	virtual void Add(Component* com)=0;
	virtual void Display(int nDepth)=0;
};

class Leaf : public Component
{
public:
	Leaf(string strName): Component(strName){}

	virtual void Add(Component* com)
	{
		cout<<"leaf can't add"<<endl;
	}

	virtual void Display(int nDepth)
	{
		string strtemp;
		for(int i=0; i < nDepth; i++)
		{
			strtemp+="-";
		}
		strtemp += m_strName;
		cout<<strtemp<<endl;
	}
};

class Composite : public Component
{
private:
	vector<Component*> m_component;
public:
	Composite(string strName) : Component(strName){}

	virtual void Add(Component* com)
	{
		m_component.push_back(com);
	}

	virtual void Display(int nDepth)
	{
		string strtemp;
		for(int i=0; i < nDepth; i++)
		{
			strtemp+="-";
		}
		strtemp += m_strName;
		cout<<strtemp<<endl;

		vector<Component*>::iterator p=m_component.begin();
		while (p!=m_component.end())
		{
			(*p)->Display(nDepth+2); 
			p++;
		}
	}

};

//client
#include "Model.h"

int main()
{
	Composite* p=new Composite("Xiao Wang");
	p->Add(new Leaf("petty thief"));
	p->Add(new Leaf("Xiao Zhao"));

	Composite* p1 = new Composite("Little five");
	p1->Add(new Leaf("Junior"));

	p->Add(p1);
	p->Display(1);
	return 0;
}

  Example 2

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Company
{
protected:
	string m_strName;
public:
	Company(string strName)
	{
		m_strName = strName;
	}

	virtual void Add(Company* c)=0;
	virtual void Display(int nDepth)=0;
	virtual void LineOfDuty()=0;
};

class ConcreteCompany: public Company
{
private:
	vector<Company*> m_company;
public:
	ConcreteCompany(string strName):Company(strName){}

	virtual void Add(Company* c)
	{
		m_company.push_back(c);
	}
	virtual void Display(int nDepth)
	{
		string strtemp;
		for(int i=0; i < nDepth; i++)
		{
			strtemp += "-";
		}
		strtemp +=m_strName;
		cout<<strtemp<<endl;

		vector<Company*>::iterator p=m_company.begin();
		while (p!=m_company.end())
		{
			(*p)->Display(nDepth+2);
			p++;
		}
	}
	virtual void LineOfDuty()
	{
		vector<Company*>::iterator p=m_company.begin();
		while (p!=m_company.end())
		{
			(*p)->LineOfDuty();
			p++;
		}
	}
};

class HrDepartment : public Company
{
public:

	HrDepartment(string strname) : Company(strname){}

	virtual void Display(int nDepth)
	{
		string strtemp;
		for(int i = 0; i < nDepth; i++)
		{
			strtemp += "-";
		}

		strtemp += m_strName;
		cout<<strtemp<<endl;
	}
	virtual void Add(Company* c)
	{
		cout<<"error"<<endl;
	}

	virtual void LineOfDuty()
	{
		cout<<m_strName<<":Recruitment of talents"<<endl;
	}
};
//client:
int main()
{
	ConcreteCompany *p = new ConcreteCompany("Tsinghua University");
	p->Add(new HrDepartment("Talent Department of Tsinghua University"));

	ConcreteCompany *p1 = new ConcreteCompany("faculty of Mathematics");
	p1->Add(new HrDepartment("Talent Department of Mathematics Department"));

	ConcreteCompany *p2 = new ConcreteCompany("physics department");
	p2->Add(new HrDepartment("Department of Physics"));

	p->Add(p1);
	p->Add(p2);

	p->Display(1);
	p->LineOfDuty();
	return 0;
}

(16) Iterator mode

GOOD: provides a way to access the elements of a convergent object sequentially without exposing the internal representation of the object.

It provides unified interfaces for traversing different aggregation structures, such as start, next, end, current, etc.

 

(17) Singleton mode

GOOD: ensure that a class has only one instance and provide a global access point to access it

  Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Singelton
{
private:
	Singelton(){}
	static Singelton* singel;

public:
	static Singelton* GetInstance()
	{
		if(singel == NULL)
		{
			singel = new Singelton();
		}
		return singel;
	}

};
Singelton* Singelton::singel = NULL;//Note that static variables are initialized out of class

client:

int main()
{
	Singelton* s1=Singelton::GetInstance();
	Singelton* s2=Singelton::GetInstance();
	if(s1 == s2)
		cout<<"ok"<<endl;
	else
		cout<<"no"<<endl;
	return 0;
}

(18) Bridging mode

GOOD: separate the abstract part from the implementation part so that they can change independently.

What we mean here is not to separate the abstract base class from the concrete class, but that the real system may have multi angle classification, and each classification may change. Then separate these multi angles, let them change independently, and reduce the coupling between them. That is, if inheritance can not realize the "open closed principle", we should consider using the bridge mode. The following example: let "mobile phone" be classified by brand or

  Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

//Mobile software
class HandsetSoft
{
public:
	virtual void Run()=0;
};

//Game software
class HandsetGame : public HandsetSoft
{
public:
	virtual void Run()
	{
		cout<<"Running mobile games"<<endl;
	}
};

//Address book software
class HandSetAddressList : public HandsetSoft
{
public:
	virtual void Run()
	{
		cout<<"Mobile phone address book"<<endl;
	}
};

//Mobile phone brand
class HandsetBrand
{
protected:
	HandsetSoft* m_soft;
public:
	void SetHandsetSoft(HandsetSoft* temp)
	{
		m_soft = temp;
	}
	virtual void Run()=0;
};

//M Brand
class HandsetBrandM : public HandsetBrand
{
public:
	virtual void Run()
	{
		m_soft->Run();
	}
};

//Brand N
class HandsetBrandN : public HandsetBrand
{
public:
	virtual void Run()
	{
		m_soft->Run();
	}
};

//client
int main()
{
	HandsetBrand *brand;
	brand = new HandsetBrandM();
	brand->SetHandsetSoft(new HandsetGame());
	brand->Run();
	brand->SetHandsetSoft(new HandSetAddressList());
	brand->Run();

	return 0;
}

(19) Command mode

GOOD: first, establish a command queue; 2, Commands can be logged; 3, The party receiving the request may refuse; 4, Adding a new command class does not affect other classes;

Command mode separates the object that requests an operation from the object that knows how to perform an operation

 

 

  Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

//Barbecue Chef
class Barbucer
{
public:
	void MakeMutton()
	{
		cout<<"roast mutton"<<endl;
	}
	void MakeChickenWing()
	{
		cout<<"Roast chicken wings"<<endl;
	}
};

//Abstract command class
class Command
{
protected:
	Barbucer* receiver;
public:
	Command(Barbucer* temp)
	{
		receiver = temp;
	}
	virtual void ExecuteCmd()=0;
};

//Roast mutton command
class BakeMuttonCmd : public Command
{
public:
	BakeMuttonCmd(Barbucer* temp) : Command(temp){}
	virtual void ExecuteCmd()
	{
		receiver->MakeMutton();
	}
};

//Roast chicken wings
class ChickenWingCmd : public Command
{
public:
	ChickenWingCmd(Barbucer* temp) : Command(temp){}

	virtual void ExecuteCmd()
	{
		receiver->MakeChickenWing();
	}
};

//Waiter class
class Waiter
{
protected:
	vector<Command*> m_commandList;
public:
	void SetCmd(Command* temp)
	{
		m_commandList.push_back(temp);
		cout<<"Add order"<<endl;
	}

	//Notification execution
	void Notify()
	{
		vector<Command*>::iterator p=m_commandList.begin();
		while(p!=m_commandList.end())
		{
			(*p)->ExecuteCmd();
			p++;
		}
	}
};

//client
int main()
{
	//Add barbecue chef, menu, waiter and other customers in the store
	Barbucer* barbucer=new Barbucer();
	Command* cmd= new BakeMuttonCmd(barbucer);
	Command* cmd2=new ChickenWingCmd(barbucer);
	Waiter* girl = new Waiter();
    //order
	girl->SetCmd(cmd);
	girl->SetCmd(cmd2);
    //Waiter notification
	girl->Notify();
	return 0;
}

(20) Responsibility chain model

GOOD: make multiple objects have the opportunity to process the request, so as to avoid the coupling relationship between the sender and receiver of the request. Connect the object into a chain and pass the request along the chain until an object handles it.

Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;
//request
class Request
{
public:
	string m_strContent;
	int m_nNumber;
};
//controller
class Manager
{
protected:
	Manager* manager;
	string name;
public:
	Manager(string temp)
	{
		name = temp;
	}
	void SetSuccessor(Manager* temp)
	{
		manager = temp; 
	}
	virtual void GetRequest(Request* request) = 0;
};
//manager
class CommonManager : public Manager
{
public:
	CommonManager(string strTemp) : Manager(strTemp){}
	virtual void GetRequest(Request* request)
	{
		if ( request->m_nNumber>=0 && request->m_nNumber<10 )
		{
			cout<<name<<"Handled"<<request->m_nNumber<<"Requests"<<endl;
		}
		else
		{
			manager->GetRequest(request);
		}
	}
};
//chief inspector
class MajorDomo : public Manager
{
public:
	MajorDomo(string name) : Manager(name){}

	virtual void GetRequest(Request* request)
	{
		if(request->m_nNumber>=10)
		{
	    	cout<<name<<"Handled"<<request->m_nNumber<<"Requests"<<endl;
		}
	}
};

//client
int main()
{
	Manager * common = new CommonManager("Manager Zhang");
	Manager * major = new MajorDomo("Director Li");
	
	common->SetSuccessor(major);
	
	Request* req = new Request();
	req->m_nNumber = 33;
	common->GetRequest(req);
	
	req->m_nNumber = 3;
	common->GetRequest(req);
	return 0;
}

 

21) Intermediary model

GOOD: a mediation object is used to encapsulate a series of object interactions. The mediator makes the objects do not need to show mutual references, so as to reduce the coupling; And the interaction between them can be changed independently.

  Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Colleague;
//Intermediary class
class Mediator
{
public:
	virtual void Send(string message,Colleague* col) = 0;
};
//Abstract colleague class
class Colleague
{
protected:
	Mediator* mediator;
public:
	Colleague(Mediator* temp)
	{
		mediator = temp;
	}
};
//Colleague 1
class Colleague1 : public Colleague
{
public:
	Colleague1(Mediator* media) : Colleague(media){}

	void Send(string strMessage)
	{
		mediator->Send(strMessage,this);
	}

	void Notify(string strMessage)
	{
		cout<<"As soon as my colleague got the news"<<strMessage<<endl;
	}
};

//Colleague 2
class Colleague2 : public Colleague
{
public:
	Colleague2(Mediator* media) : Colleague(media){}

	void Send(string strMessage)
	{
		mediator->Send(strMessage,this);
	}

	void Notify(string strMessage)
	{
		cout<<"Colleague 2 got the news"<<strMessage<<endl;
	}
};

//Specific intermediary class
class ConcreteMediator : public Mediator
{
public:
	Colleague1 * col1;
	Colleague2 * col2;
	virtual void Send(string message,Colleague* col)
	{
		if(col == col1)
			col2->Notify(message);
		else 
			col1->Notify(message);
	}
};

//client:
int main()
{
	ConcreteMediator * m = new ConcreteMediator();

	//Let colleagues know the intermediary
	Colleague1* col1 = new Colleague1(m);
	Colleague2* col2 = new Colleague2(m);

	//Let the intermediary know specific colleagues
	m->col1 = col1;
	m->col2 = col2;

	col1->Send("have you had dinner");
	col2->Send("I haven't eaten yet. Will you treat me?");
	return 0;
}

(22) Sharing element mode

GOOD: use sharing technology to effectively support a large number of fine-grained objects (for C + +, it means sharing a memory block, and the object pointer points to the same place).

      If an application uses a large number of objects and these objects cause great storage overhead, it should be considered.

      In addition, most states of objects can be external states. If you delete the external states of objects, you can replace multiple groups of objects with fewer shared objects. At this time, you can consider using shared objects.

  Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

//Abstract website
class WebSite
{
public:
	virtual void Use()=0;
};

//Specific shared websites
class ConcreteWebSite : public WebSite
{
private:
	string name;
public:
	ConcreteWebSite(string strName)
	{
		name = strName;
	}
	virtual void Use()
	{
		cout<<"Site classification:"<<name<<endl;
	}
};

//Unshared sites
class UnShareWebSite : public WebSite
{
private:
	string name;
public:
	UnShareWebSite(string strName)
	{
		name = strName;
	}
	virtual void Use()
	{
		cout<<"Unshared sites:"<<name<<endl;
	}
};

//The site factory class is used to store shared WebSite objects
class WebFactory
{
private:
	vector<WebSite*> websites;
public:
	WebSite* GetWeb()
	{
		vector<WebSite*>::iterator p = websites.begin();
		return *p;
	}
	WebFactory()
	{
		websites.push_back(new ConcreteWebSite("test"));
	}
};

//client
int main()
{
	WebFactory* f= new WebFactory();
	WebSite* ws= f->GetWeb();
	ws->Use();

	WebSite* ws2 = f->GetWeb();
	ws2->Use();

	//Unshared classes
	WebSite* ws3 = new UnShareWebSite("test");
	ws3->Use();
	return 0;
}

(23) Interpreter mode

GOOD: usually, when a language needs interpretation and execution, and you can represent the sentences in the language as an abstract syntax tree, you can use the Interpreter pattern.

Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Context;
class AbstractExpression
{
public:
	virtual void Interpret(Context* context)=0;
};

class Expression : public AbstractExpression
{
public:
	virtual void Interpret(Context* context)
	{
		cout<<"Terminal interpreter"<<endl;
	};
};

class NonterminalExpression : public AbstractExpression
{
public:
	virtual void Interpret(Context* context)
	{
		cout<<"Non terminal interpreter"<<endl;
	}
};

class Context
{
public:
	string input;
	string output;
};

//client
int main()
{
	Context* context = new Context();
	vector<AbstractExpression*> express;
	express.push_back(new Expression());
	express.push_back(new NonterminalExpression());
	express.push_back(new NonterminalExpression());

	vector<AbstractExpression*>::iterator p = express.begin();
	while (p!= express.end())
	{
		(*p)->Interpret(context);
		p++;
	}

	return 0;
}

 

(24) Visitor mode

GOOD: suitable for systems with stable data structure. It separates the data structure from the operations acting on the data structure, making the operation set

      Advantages: adding new operations is easy, because adding new operations is equivalent to adding a visitor. The visitor pattern focuses the relevant behaviors into a visitor object

  Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Man;
class Woman;
//behavior
class Action
{
public:
	virtual void GetManConclusion(Man* concreteElementA)=0;
	virtual void GetWomanConclusion(Woman* concreteElementB)=0;
};
//success
class Success : public Action
{
public:
	virtual void GetManConclusion(Man* concreteElementA)
	{
		cout<<"When a man succeeds, there is a great woman behind him"<<endl;
	}
	virtual void GetWomanConclusion(Woman* concreteElementB)
	{
		cout<<"When a woman succeeds, there is a useless man behind her"<<endl;
	}
};

//fail
class Failure : public Action
{
public:
	virtual void GetManConclusion(Man* concreteElementA)
	{
		cout<<"When a man fails, there is a great woman behind him"<<endl;
	}
	virtual void GetWomanConclusion(Woman* concreteElementB)
	{
		cout<<"When a woman fails, there is a useless man behind her"<<endl;
	}
};

//Abstract human
class Person
{
public:
	virtual void Accept(Action* visitor)=0;
};

//man
class Man : public Person
{
public:
	virtual void Accept(Action* visitor)
	{
		visitor->GetManConclusion(this);
	}
};

//woman
class Woman : public Person
{
public:
	virtual void Accept(Action* visitor)
	{
		visitor->GetWomanConclusion(this);
	}
};

//Object structure class
class ObjectStructure
{
private:
	vector<Person*> m_personList;

public:
	void Add(Person* p)
	{
		m_personList.push_back(p);
	}
	void Display(Action* a)
	{
		vector<Person*>::iterator p = m_personList.begin();
		while (p!=m_personList.end())
		{
			(*p)->Accept(a);
			p++;
		}
	}
};

//client
int main()
{
	ObjectStructure * os= new ObjectStructure();
	os->Add(new Man());
	os->Add(new Woman());

	Success* success = new Success();
	os->Display(success);

	Failure* fl = new Failure();
	os->Display(fl);
	
	return 0;
}

Topics: Design Pattern