The most common design patterns
Design Patterns are usually reusable solutions for a type of software design problems. The purpose of introducing design patterns into the software design and development processes is to make full use of existing software development experience.
Based on my experience, I will summarize the frequently used design patterns here. According to my experience, they are sorted as follows: 1) single-piece mode, 2) abstract Factory mode and factory mode; 3) Adapter mode; 4) Decoration mode; 5) Observer mode; 6) Appearance mode; other modes are rarely used at present.
Single-piece Mode
This is the most widely used mode. Every formal software should use it. Global configuration, unique resources, and one is that all factories are designed as single-piece models, therefore, its usage is greater than the sum of the factory mode and the abstract factory mode. Is used to create a globally unique instance. It just needs to be corrected. In Singleton mode, the constructor should be protected. This way the subclass can extend this constructor.
The single-piece mode is mainly used in the following scenarios:
1. A Class occupies a lot of system resources. These resources can be shared globally, and can be designed as Singleton mode, forcing only one instance globally
2. For a class, the instance needs to be counted. You can create and limit the number of instances in createinstance.
3. For a class, you need to control the specific behavior of its instance. For example, you want the returned instance to be an instance of its own subclass. In this way, you can use Singleton mode Code Transparent.
The Singleton mode is a relatively simple mode. The following Code creates a singlton mode example, which is a class for writing system logs, the practical application is to save only one instance in the memory to avoid consuming system resources by opening multiple tool-class instances with the same functions. It is particularly meaningful when multiple applications call the same tool class or control class. It is recommended that you use it during development.
Public class logwriter
{
// Declare a static variable of the class itself
Private Static logwriter _ instance = NULL;
// Privatize the class constructor so that this class cannot be created by the outside world
Private logwriter ()
{
}
// Provides a static method to create a class instance
Public static logwriter getinstance ()
{
If (_ instance = NULL)
{
_ Instance = new logwriter ();
}
Return _ instance;
}
}
Analysis: How to maintain the single-piece mode when multiple threads are used?
A: It should be a single piece when multithreading, because the threads share the memory.
What if I want to limit the number of instances to 10?
A: Do something like a thread pool.
Multithreading can also be used below, there are many ways
1. Synchronize static methods; 2. eager to create instances; 3. Double check and lock
Public class Singleton {
Private volatile static Singleton;
Private Singleton (){}
Public Singleton (string name ){}
Public static Singleton getinstance (){
If (Singleton = NULL ){
Synchronized (singleton. Class ){
If (Singleton = NULL ){
Singleton = new Singleton ();
}
}
}
Return Singleton;
}
}
Singleton mode: The implementation of Singleton mode is very similar to the last one in the evolution of the previous mode, as long as the constructor is private.
Simple factory Mode
The simple factory mode is determined by a factory object to create a product instance. The simple factory model is the simplest and Practical Model in the factory model family. It can be understood as a special implementation of different factory models.
Public class steamedbread
{
Public steamedbread () // Constructor
{}
Private double prices = 0.5;
Public double price
{
Get {return price ;}
Set {price = value ;}
}
}
OK. The product object has been created. The following figure shows how to create a factory object.
Public class factory
{
Public static steamedbread createinstance () // create a steamedbread object
{
Return new steamedbread ();
}
}
In this case, the client can call:
Public class client
{
Public static void main (string [] ARGs)
{
// Create a product instance through the factory
Steamedbread sb = factory. createinstance ();
Console. writeline ("Shantou {0} RMB one! ", SB. Price );
}
}
Factory Model
Public interface ifruit
{
}
Public class orange: ifruit
{
Public orange ()
{
Console. writeline ("an orange is got! ");
}
}
Public class Apple: ifruit
{
Public Apple ()
{
Console. writeline ("an apple is got! ");
}
}
What should we do with our fruitfactory? In the above structure diagram, it gives createproducta. Well, I will make orange, and there is a createproductb. Isn't makeorange enough ??
Public class fruitfactory
{
Public orange makeorange ()
{
Return new orange ();
}
Public Apple makeapple ()
{
Return new Apple ();
}
}
How can we use this factory? Let's write down the following code:
String fruitname = console. Readline ();
Ifruit myfruit = NULL;
Fruitfactory myfruitfactory = new fruitfactory ();
Switch (fruitname)
{
Case "orange ":
Myfruit = myfruitfactory. makeorange ();
Break;
Case "apple ":
Myfruit = myfruitfactory. makeapple ();
Break;
Default:
Break;
}
Abstract Factory Model
The schematic code is as follows:
/// <Summary>
// Food interface ---- playing the abstract Product role
/// </Summary>
Public interface ifood
{
/// <Summary>
/// Each type of food has a sales price, which should be promoted to the parent class or interface as a common property.
/// Because we only need to get the price, only the get attribute accessors are provided here.
/// </Summary>
Double price {Get ;}
}
Bytes ------------------------------------------------------------------------------------
/// <Summary>
/// Steamed bread
/// </Summary>
Public class steamedbread: ifood
{
/// <Summary>
/// Constructor
/// </Summary>
Public steamedbread ()
{}
Public double price
{
Get
{
Return 0.5;
}
}
}
Bytes ------------------------------------------------------------------------------------
/// <Summary>
/// Steamed stuffed bun
/// </Summary>
Public class steamedstuffed: ifood
{
Public steamedstuffed ()
{}
/// <Summary>
/// Sales price
/// </Summary>
Public double price
{
Get
{
Return 0.6; // 0.6 RMB
}
}
}
Bytes ------------------------------------------------------------------------------------
/// <Summary>
/// Factory role
/// </Summary>
Public class factory
{
/// <Summary>
/// Create a steamed bun (steamedbread) object
/// </Summary>
/// <Returns> </returns>
Public static ifood createinstance (string key)
{
If (Key = "Shantou ")
{
Return new steamedbread ();
}
Else
{
Return new steamedstuffed ();
}
}
}
Bytes ------------------------------------------------------------------------------------
Public class client
{
Public static void main (string [] ARGs)
{
// Create a product instance through the factory
Ifood food = factory. createinstance ("Shantou ");
Console. writeline ("Shantou {0} RMB one! ", Food. Price );
Food = factory. createinstance ("steamed stuffed bun ");
Console. writeline ("$ {0} $! ", Food. Price );
}
}
At this time, the design is completely in line with the intention of the simple factory model. The customer (client) told the breakfast shop clerk (factory) That I wanted "steamed bread", so the clerk went to the numerous foods according to the data (steamed bread) provided by the customer, find it and give it to the customer.
Other Modes
Adapter Mode
The scheme mode has two types of adapters and object adapters. The Object Adapter has more. The advantages of the Object Adapter have been discussed n times by many heroes. I am not talking about it here, I also use one of the many reasons. I switched from C ++ to C #. Since C # does not support multiple inheritance, I am not too lazy and have fewer interface definitions, therefore, you can only use the Object Adapter mode when using C # in most cases. In fact, there is a great similarity between the adapter and the decoration mode, which will be discussed in the following decoration mode.
Decoration Mode
It is also called the painter mode. Similar to the adapter mode, the decoration mode is used to adjust ready-made code to meet new requirements. In fact, one of the purposes of using the design mode is reuse, these two models are exactly the embodiment of reuse. When you use these two modes, you add new features to your existing software. Generally, if you want to add new functions to your software, you usually need to use the decoration mode. If you want to add function support for the software, you 'd better select the adapter mode. If you want to add operations for your class, you should use the decoration mode, if you want to introduce off-the-shelf code from other sources, you use the adapter mode.
Observer Mode
One more reason I use this mode is that it can implement the event function. Of course, the event can be directly used in C, however, in C ++, the model can be used to give full play to its full potential. An online question (the cat shouted, and the host woke up and ran away ), it is the best application to use this mode.
Appearance Mode
Development is to reuse where it can be reused to save resources and improve efficiency. The appearance mode is also a solution that provides reuse of other ready-made code. You need to implement a function, this function may be available in the ready-made code, but the ready-made code may be much more than what you need. In this case, You encapsulate these functions and re-provide the interface you need, this is the essence of this model.
1. Static members:
Attributes, methods, and fields are unique to object instances. Static members can be viewed as global objects of classes. Static attributes and fields can access data independent from any object instance. Static methods can execute commands related to object types and irrelevant to object instances. Objects do not need to be instantiated when static members are used. Static fields, attributes, and methods cannot be called by instances.
2. Static class:
it only contains static members. It cannot be instantiated, sealed, and does not need to be defined by constructors.