Design pattern


principle:
Single responsibility principle: a class has a single responsibility and only provides one function
Opening and closing principle: class changes are realized by adding code, not modifying the source code; For extension development, close for modification
Dependency Inversion Principle: for interface programming, it depends on abstraction rather than concrete implementation
Creating: how to create objects
Struct: a combination of classes or objects
Behavior: how classes or objects interact

1. Singleton mode

A class can have at most one instance and provides a global access point
Used for: resource management, thread pool and log management
Implementation method:
Class constructor and copy constructor are private, and external construction of instances is prohibited;
The static function is defined in the class to return a unique instance and set it to public

class A{
private: 
	A(){cout<<"Chinese"<<endl;};
	A(const A& other);

public: static A* aaa();
		static A *a;
};

1.1 single lazy type

Delay the creation and create when the object is used. Static member variables can only be declared inside the class. Outside the class, nullptr is not initialized first

Lazy, instantiated only when called, non thread safe

A * A::a = nullptr;//Static member variables can only be declared inside the class and initialized outside the class 
 A* A :: aaa(){
	 if(a == nullptr){
		 a = new A();
	 }
	 return a; 
 }

The solution is to lock, but the cost of locking is too high. Locking the read thread is a waste

 A* A :: aaa(){
     Lock lock;
    if(a == nullptr){
   	 a = new A();
    }
    return a; 
}

The solution is to double detect the lock. In case of problems, when the compiler executes new A, the order is unconventional. Normally, 1 opens up space, 2 calls the constructor to initialize the memory, and 3 returns the address to a; If the compiler changes the order of 23 and the first thread comes here, a is not empty. At this time, if thread B comes, it will directly access the memory that does not execute the constructor, and an error will be reported

A* A:: aaa(){
    if(a == nullptr){
  	  Lock lock;
  	  if(a == nullptr){
  		  a = new A();
  	  }	  
    }
    return a;  
}

1.2 single case hungry Han style

Direct instantiation, created before the program starts, is thread safe

A * A:: aaa(){
	return a;
}
A * A::a = new A();  //new objects, three parts open up space, call to construct initialization memory and return pointers, so they should be received with pointers

2. Factory

Factories are used to produce products; Is a class that is responsible for creating instances of other classes

2.1 simple factory mode

Simple factory mode is a class responsible for creating instances of other classes. It can return different instances according to different parameters. These instances have a common parent class; All this pattern is responsible for which classes in a large class need instances
Disadvantages: Contrary to the opening and closing principle, the factory class needs to be modified when adding functions. When there are many function classes, the logical structure is complex
Implementation method:

Fruit abstract base class
Specific categories of various fruits
Fruit factory

  1. An abstract fruit
class friut{
public:
	virtual void showname() = 0;
};
  1. Two specific fruits
class apple:public friut{
public: 
	void showname(){
		cout<<"apple successfully"<<endl;
	
	}
};	

class pear:public friut{
public: 
	void showname(){
		cout<<"pear successfully"<<endl;
	
	}
};	

3. A fruit processing plant

class factory{
public:
	 friut* fruit(string f){//Why static
		if(f == "apple"){
			return new apple;
		}
		else return new pear;
	
	}
};

realization

void main() 
{
	 factory * p = new factory();
	 friut * apple = p->fruit("apple");
	 apple->showname(); 
}

2.2 factory method mode = simple + open close

Define an interface for creating objects, and let subclasses decide which class to instantiate
Avoid creating objects with new. Creating objects with new will depend on specific classes, which cannot be changed later,

Disadvantages: too many classes and high maintenance cost

Implementation method:
A car abstract base class
An abstract base class of automobile factory
Automobile specific category
Specific categories of automobile factory

1. Abstract product automobile

//Abstract product automobile
class Car{
public:
	virtual void carname() = 0;
};

2. Plant base class

//Factory base class
class CarFactory{
public:
	virtual Car* carFactoryname() = 0;
};

3. Two specific categories of vehicles

//Automobile subclass
class Benz:public Car{
public:
	void carname(){
		cout<<"I am Benz"<<endl;
	}
};
class Audi:public Car{
public:
	void carname(){
		cout<<"I am Audi"<<endl;
	}
};

4. Two specific automobile processing plants

//Specific processing plant
class BenzFactory:public CarFactory{
public:
	//Build a Mercedes
	 Car * carFactoryname(){
		return new Benz;	
	}
};
class AudiFactory:public CarFactory{
public:
	Car * carFactoryname(){
		return new Audi;	
	}
};

realization:

void main(){
	//The above are all classes. To start building a car, first instance a processing plant
	CarFactory *factory = nullptr; 
	Car* car = nullptr;

	 factory = new BenzFactory(); //The parent class pointer points to different subclass objects
	 car = factory->carFactoryname();
	 car->carname();
}

2.3 Abstract Factory

The automobile factory began to build trains in the following ways:

Abstract product automobile
Specific classes

Abstract product train
Specific classes

An abstract processing plant
Specific category of processing plant

//Expand production, automobile + train

//Product A abstract and concrete automobile
class Car{
public:
	virtual void showCarname()=0;
};

class BenzCar:public Car{
public:
	void showCarname(){
		cout<< "Car-Benz"<<endl;
	
	}

};
class AudiCar:public Car{
public:
	void showCarname(){
		cout<< "Car-Audi"<<endl;
	
	}

};
//Product B Abstract and concrete classes
class Train{
public:
	virtual void showTrainname()=0;
};
class BenzTrain:public Train{
public:
	void showTrainname(){
		cout<< "Train-Benz"<<endl;
	
	}
};
class AudiTrain:public Train{
public:
	void showTrainname(){
		cout<< "Train-Benz"<<endl;
	
	}
};

//Abstract factory
class Factory{
public:
	virtual Car* carfactory() = 0;
	virtual Train* Trainfactory() = 0;

};
//Specific factory
class Benzfactory:public Factory{
public:
	Car* carfactory() {
		return new BenzCar;
	}
	Train* Trainfactory(){
		return new BenzTrain;
	
	}

};

class Audifactory:public Factory{
public:
	Car* carfactory() {
		return new AudiCar;
	}
	Train* Trainfactory(){
		return new AudiTrain;
	
	}

};

realization:

void main(){
	Car * car = nullptr;
	Train * train = nullptr;
	Factory * factory = nullptr;

	//Mercedes Benz cars and trains
	factory = new Benzfactory();
	car = factory->carfactory();
	car->showCarname();	
	train = factory->Trainfactory();
	train->showTrainname();

	delete factory;
	delete car;
	delete train;
	

	//Audi cars and trains
	factory = new Audifactory();
	car = factory->carfactory();
	car->showCarname();	
	train = factory->Trainfactory();
	train->showTrainname();
	


}

Added by merrydown on Tue, 04 Jan 2022 01:17:12 +0200