Background
Break News
How to add local font to Tailwind Css and NextJS? - Tutorial Design Pattern? - Blockchain Technology, How to create own Bitcoin virtual currency - Zustand mordern management state - Design Pattern - Flyweight Pattern? - Docker Full training Topic

[Tutorial] Design Pattern - Strategy Pattern

Thursday, 21 July 2016
|
Read: Completed in minutes

[Tutorial] Design Pattern - Strategy Pattern

"Encapsulates an algorithm inside a class"


A Strategy defines a set of algorithms that can be used interchangeably. Modes of transportation to an airport is an example of a Strategy. Several options exist such as driving one's own car, taking a taxi, an airport shuttle, a city bus, or a limousine service. For some airports, subways and helicopters are also available as a mode of transportation to the airport. Any of these modes of transportation will get a traveler to the airport, and they can be used interchangeably. The traveler must chose the Strategy based on trade offs between cost, convenience, and time.




Rules of thumb

- Strategy is like Template Method except in its granularity.
- State is like Strategy except in its intent.
- Strategy lets you change the guts of an object. Decorator lets you change the skin.
- State, Strategy, Bridge (and to some degree Adapter) have similar solution structures. They all share elements of the 'handle/body' idiom. They differ in intent - that is, they solve different problems.
- Strategy has 2 different implementations, the first is similar to State. The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic).
- Strategy objects often make good Flyweights.


Strategy Pattern

Download full source code here

Các lập trình viên tại MegaGigaCo (phần đầu chương) đều biết về sự “kế thừa” và họ bắt đầu việc thíêt kế xe hơi mới bất chấp lời cảnh báo của bạn cho đến khi bạn có cơ hội nói chuyện với họ. Họ biết họ đang phải thiết kế một loạt xe, vì vậy họ bắt đầu tạo ra một lớp cơ sở tên Vehicle với một phương thức tên là go, phương thức này xuất hiện lên dòng chữ Now I’m driving.




 
public abstract class clsVehicle
        {
            public clsVehicle()
            {
            }
        
            public void go()
            {
                 Console.WriteLine("Now, I'm driving");
            }
        }
        

Sau đó họ tao tiếp một lớp mới, như là lớp StreetRacer, sử dụng Vehicle làm lớp cơ sở như sau:

public class clsStreetRacer:clsVehicle
        {
         public clsStreetRacer()
         {
         }
        }
        

Chương trình tới đây vẫn tốt đẹp. Bạn có thể cho chạy chương trình với lớp StreetRacer như sau:


static void Main(string[] args)
        { 
         clsStreetRacer streetRacer = new clsStreetRacer(); 
         streetRacer.go();
         
         Console.ReadLine();
        }
        

Kết quả nhận được
=> Now I'm driving

Bạn cũng có thể chạy cùng lúc street racer và formula one racer với cùng một cách như sau:

static void Main(string[] args)
        {
            clsStreetRacer streetRacer = new clsStreetRacer();
            clsFormulaOne formulaone = new clsFormulaOne();
            clsHelicopter helicopter = new clsHelicopter(); 
                            
            streetRacer.go();
            formulaone.go();
            helicopter.go();
            Console.ReadLine();
        }
        

Kết quả nhận được
=> Now I'm driving
=> Now I'm driving
=> Now I'm driving

“Không tồi”. Giám đốc và ban điều hành nói. “Vậy cần gì phải sử dụng mẫu thiết kế” Họ hỏi mà mắt nhìn chằm chằm vào bạn. Nhưng sau đó họ nhận được một hợp đồng sản xuất máy bay trực thăng Helicopter. Máy bay trực thăng à? Họ lý luận, thì cũng là một phương tiện vận chuyển. Vì vậy họ tạo một lớp Helicopter , được mở rộng ra từ lớp Vehicle :

Trên kia bạn có sử dụng thêm lớp helicopter. Nhưng lại xuất hiện một vấn đề. Nếu như bạn sử dụng helicopter trong cùng một điều kiện như xe hơi:

Bạn sẽ nhận được 3 phương tiện như sau: một xe street racer, một xe Formula One, một máy bay helicopter như sau:

Kết quả nhận được
=> Now I'm driving
=> Now I'm driving
=> Now I'm driving

Có gì đó không ổn, Giám đốc nói một cách hồ nghi. Tại sao helicopter (máy bay trực thăng) mà lại đang chạy? Hình như nó đang bay thì mới đúng? Tuy nhiên vấn đề thực sự tồi tệ khi công ty MegaGigaCo nhận được một hợp đồng chế tạo máy bay phản lực Jet, khi đó chúng cũng được kế thừa từ lớp Vehicle :

Khi bạn cho chạy bốn phương tiện trên: một xe street racer, một xe formula one, một máy bay trực thăng helicopter, một máy bay phản lực jet, bạn nhận được kết quả sau:


Kết quả nhận được
=> Now I'm driving
=> Now I'm driving
=> Now I'm driving
=> Now I'm driving 

“Chắc chắn là đã có sai sót ở đây” Vị giám đốc lên tiếng. Máy bay phản lực Jet thì không chạy trên đường, chúng ở trên không. Chúng bay và rất nhanh. Không vấn đề gì, các lập trình viên trong công ty đáp. Chúng tôi sẽ override lên phương thức go của lớp Helicopter và lớp Jet để sửa chữa chúng. Họ chỉnh sửa lại như sau:

public class clsHelicopter:clsVehicle
        {
            public clsHelicopter() 
            { 
                setGoAlgorithm(new clsGoByFlyingAlgorithm());
            }    
        
            public void go()
            {
                Console.Writeln("Now I'm flying!");
            }             
        }
        

Giờ lớp máy bay trực thăng Helicopter đã bay được.

“OK”. Giám đốc nói “Tuy nhiên vào tuần sau, ban giám đốc họp và quyết định phải chuyển từ “Now I’m flying” sang “Now, I’m flying 200mph” và nhiều sự thay đổi tồi tệ kế tiếp…

Có một vấn đề nảy sinh ở đây, bạn giải thích. Các lập trình viên đã thể hiện một chức năng đơn giản – là lái một chiếc xe hay một chiếc phi cơ – qua nhiều lớp con. Đó có thể chưa là một vấn đề lớn nhưng nếu bạn xử lý các công việc này một cách khá thường xuyên, thì việc phải chỉnh sửa mọi lớp con như vậy sẽ trở thành một vấn đề bảo trì khá nghiêm trọng.

Bạn nói tiếp: có thể là “sự kế thừa” không phải là câu trả lời cho tình huống này. Nơi mà bạn cần phải thay đổi chức năng thường xuyên ở các lớp con. Bạn cần phải chỉnh sửa, bảo trì phần lớn các đoạn mã ở các lớp con khi có sự thay đổi. Và khi có càng nhiều lớp kế thừa liên quan, chúng cũng cần được phải bảo trì khi có sự thay đổi, và khi đó bạn phải cập nhật các phương thức go mãi mãi.
Vấn đề bạn phải giải quyết ở đây là làm sao tránh được việc thay đổi ở các lớp con. Nếu bạn không tránh được điều này, bạn sẽ phải chỉnh sửa rất nhiều file để cập nhật mã của bạn.
Có lẽ có một cách tốt hơn để xử lý vấn đề này hơn là sử dụng sự “kế thừa”.

“Hey” một lập trình viên nói, “Sao anh không sử dụng giao diện interface thay cho sự kế thừa inheritance? Anh có thể cài đặt một giao diện IFly và cho giao diện đó một phương thức go và để cho lớp Helicopter hiện thực giao diện đó như sau:

public class clsHelicopter : IFly
        {
            public clsHelicopter() 
            { 
            }
            
            public void go()
            {
                Console.Writeln("Now I'm flying!");
            }      
               
        }
        

“Không tốt” bạn nói. Anh vẫn chưa giải quyết ổn thỏa vấn đề. Mỗi lớp và lớp con vẫn phải hiện thực cho riêng nó một giao diện, cũng giống như trường hợp của sự kế thừa. Bởi vì giao diện thì không cài đặt nội dung, bạn vẫn phải viết code cho từng lớp, điều này có nghĩa là chẳng có sử dụng lại được một đoạn code nào cả.

Nắm vững sự thay đổi từ “is-a” sang “has-a”


Mọi việc đều thay đổi. Trong thời buổi thương mại phát triển, mọi thứ thay đổi nhanh chóng. Vì vậy việc lập kế hoạch cho sự thay đổi là rất đáng giá. Nếu bạn có một vấn đề nhỏ cần phải có một giải pháp nhỏ, bạn có thể không cần phải lập một kế hoạch lớn lao cho sự thay đổi. Nhưng nếu bạn làm việc trong một dự án nghiêm túc, với một khối lượng công việc đáng kể, thì đúng là lúc bạn nên nhìn lại về một kế hoạch nghiêm túc khi có sự thay đổi. Các đoạn mã mà bạn viết hôm nay, sẽ phải chỉnh sửa lại để phù hợp với những yêu cầu phát triển trong tương lai. Hầu hết các nhà phát triển không chú ý tới vấn đề này, và sau đó họ luôn luôn hối tiếc. Vậy câu hỏi đặt ra là dự án phải lớn tới đâu, để bạn quan tâm đến vấn đề thay đổi. Đó là sự đánh giá của riêng bạn, một phần của nghệ thuật lập trình. Bằng cách nắm vững phương pháp xử lý sự thay đổi, bạn sẽ biết rõ hơn khi nào thì nên thực hiện nó.

Có một dấu hiệu đáng chú ý ở đây: Phân chia các đoạn mã dễ thay đổi trong chương trình riêng biệt với phần còn lại. Và làm cho chúng càng độc lập càng tốt cho sự bảo trì nâng cấp. Bạn cũng nên cố gắng tái sử dụng những phần này càng nhiều càng tốt.

Điều này có nghĩa là nếu ứng dụng của bạn có một phần bị thay đổi, bạn có thể đem nó riêng ra, sau đó thay đổi từng phần riêng biệt một cách dễ dàng trong khi vẫn không bị ảnh hưởng bởi những tác dụng phụ của nó.

Và đây là cách để lập kế hoạch cho sự thay đổi, và vì sao “kế thừa” lại không thể giải quyết tốt các sự thay đổi này. Với sự kế thừa, lớp cơ sở và các lớp con có một mối quan hệ “is-a”. Ví dụ , lớp Helicopter có quan hệ “is-a” với lớp Vehicle, điều này có nghĩa Helicopter thừa kế mọi thứ từ Vehicle, và nếu bạn phải chỉnh sửa các phương thức này, bạn sẽ gặp phải vấn đề bảo trì nó trong tương lai. Lớp cơ sở xử lý phương thức theo một cách, và lớp kế thừa lại thay đổi nó, và lớp kế tiếp lại thay đổi nó thêm một lần nữa. Và cuối cùng bạn có một lô một lốc các biến thể của  cùng 1 phương thức qua các lớp con.

Mặc khác, nếu bạn có thể trích những đoạn code dễ thay đổi và đóng gói chúng vào đối tượng, bạn có thể sử dụng các đối tượng này khi cần. Nhiệm vụ mới là xử lý trên các đối tượng này. Bạn đã không để việc xử lý lây lan qua các lớp con. Làm như vậy sẽ cho phép bạn chỉnh sửa mã của bạn bằng việc tạo ra  “sự kết hợp” composites các đối tượng. Với composites “kết hợp” này, bạn có thể dễ dàng chọn ra và sử dụng đối tượng cần thiết. Một quan hệ “has-a” mới được tạo ra. Một chiếc xe street racer sẽ có một “has-a” cách để di chuyển, đã được đóng gói vào đối tượng. Một máy bay trực thăng sẽ có một cách riêng để di chuyển, và cũng được đóng gói vào đối tượng. Từng đối tượng sẽ thực hiện hành động của riêng nó.

Một đối tượng, một nhiệm vụ thường là có ý nghĩa hơn là việc kế thừa các lớp, và tạo ra hàng tá các lớp con. Nói cách khác, chúng ta sắp xếp lại dựa trên nhiệm vụ của lớp, chứ không phải trên sự kế thừa.

Sử dụng kế thừa sẽ tự động cài đặt mọi thuộc tính một cách nghiêm ngặt, bao gồm cả quan hệ “is-a”, là thứ gây ra các rắc rối khi bảo trì cũng như khi mở rộng. Nếu bạn đặt kế hoạch cho sự thay đổi, bạn nên nghĩ tới quan hệ “has-a” , nơi mà mã của bạn bao gồm nhiều đối tượng mà có thể dễ dàng cập nhật khi có sự thay đổi xảy ra.

Gợi ý: Khi có kế hoạch cho sự thay đổi, hãy thay thế quan hệ “is-a” thành quan hệ “has-a” và đặt các đoạn mã dễ thay đổi vào các đối tượng trong ứng dụng này hơn là kế thừa chúng.

Kế hoạch chỉnh sửa code


Làm thế nào mà ý tưởng phân chia các đoạn mã dễ thay đổi sẽ hoạt động trong ví dụ Vehicle/StreetRacer/Helicopter đã nhắc trước đây. Theo ý kiến của giám đốc điều hành, phần được thay đổi nhiều nhất là phương thức go , do đó chúng ta sẽ tách nó ra. Trong thuật ngữ về thiết kế mẫu, mỗi cách hiện thực một phương thức được gọi là 1 thuật toán(algorithm) hay có thể gọi là 1 chiến lược (strategy). Vì vậy bạn có thể tạo một tập hợp các giải thuật để sử dụng cho các biến của bạn như StreetRacer, FormulaOne, Helicopter, và Jet . Làm như thế để phân chia các đoạn mã dễ thay đổi vào trong thuật toán. Từng thuật toán sẽ hoàn thành 1 nhiệm vụ.

Cách tạo thuật toán


Để chắc chắn mọi thuật toán đều hiện thực cùng một phương thức (phương thức go ở trên). Bạn cần phải tạo một giao diện interface cho nó như sau:

public interface IGoAlgorithm
        {
            void go();
        }
        

Giao diện GoAlgorithm có một phương thức duy nhất go. Để chắc chắn rằng mọi thuận toán có thể được sử dụng bởi bất kì lớp Vehicle nào, ta cần phải hiện thực interface này. Thuật toán đầu tiên GoByDrivingAlgorithm , sẽ hiển thị văn bản “Now I’m driving”. Và đây là mã của thuật toán:

public class clsGoByDrivingAlgorithm:IGoAlgorithm
        {
            public void go()
            {
                Console.WriteLine("Now, I'm driving!");
            }
        }
        


Ngoài ra, thuật toán GoByFlying, sẽ hiển thị văn bản Now I’m flying. Mã như sau:

public class clsGoByFlyingAlgorithm:IGoAlgorithm{
        
                public void go()
                {
                    Console.WriteLine("Now, I'm Flying!");
                }
        }
        

Tương tự với GoByFlyingFast...

 Tuyệt vời. Bạn vừa phân chia các thuật toán của mình ra khỏi phần mã. Bạn đang thực hiện thao tác thực thi quan hệ “has-a” hơn là quan hệ “is-a”. Bây giờ bạn đã có thể đưa các thuật toán này vào sử dụng.

Sử dụng chúng như thế nào?


Bạn đang có một số thuật toán, bạn có thể tạo các đối tượng và sử dụng quan hệ “has-a” thay cho “is-a”. Sau khi bạn tạo một đối tượng từ một thuật toán, bạn cần phải lưu trữ đối tượng ở đâu đó. Vì vậy hãy thêm vào lớp cơ sở Vehicle, một phương thức mới SetGoAlgorithm. Phương thức này sẽ lưu trữ thuật toán mà bạn muốn sử dụng. Mã như sau:


        public abstract class clsVehicle
        {
            private IGoAlgorithm _goAlgorithm;
        
            public clsVehicle()
            {
            }
        
            
            public void setGoAlgorithm(IGoAlgorithm algorithm)
            {
                _goAlgorithm = algorithm;
            }
        
        } 
        

Bây giờ khi bạn muốn sử dụng một thuật toán cụ thể nào đó ở lớp kế thừa, tất cả việc cần làm là gọi
phương thức setGoAlgorithm với một đối tượng thuật toán đúng, theo cách như sau:

public class clsStreetRacer:clsVehicle
        {
            public clsStreetRacer()
            {
                setGoAlgorithm(new clsGoByDrivingAlgorithm());
            }
        }
        

Phương thức go của lớp Vehicle có chút thay đổi. Trước đây là:

public void go()
        {
             // Phương thức go của lớp Vehicle có chút thay đổi. Trước đây là:
             // Console.WriteLine("Now, I'm driving");
        
             // Tuy nhiên, bây giờ nó phải gọi phương thức đã được định nghĩa ở các lớp thuật toán. Mã mới như sau:
             _goAlgorithm.go();
        } 
        

Bây giờ thì tất cả những gì phải làm là chọn đúng thuật toán mà bạn muốn sử dụng cho phương tiện nào đó. Ví dụ với street racer sẽ là thuật toán GoByDrivingAlgorithm,
Formula One sẽ là thuật toán GoByDrivingAlgorithm Helocopter dùng GoByFlyingAlgorithm, phản lực Jet sẽ dùng: GoByFlyingFastAlgorithm, code như sau

public class clsFormulaOne:clsVehicle
        {
            public clsFormulaOne()
            {
                setGoAlgorithm(new clsGoByDrivingAlgorithm());
            }
        }
        
        public class clsHelicopter:clsVehicle
        {
            public clsHelicopter() 
            { 
                setGoAlgorithm(new clsGoByFlyingAlgorithm());
            }       
        }    
            
        public class clsJet:clsVehicle
        {
            public clsJet()
            {
                setGoAlgorithm(new clsGoByFlyingFastAlgorithm());
            }
        }
        

Đã đến lúc chạy thử chương trình. Biên dịch và chạy thử chương trình như sau:

static void Main(string[] args)
        {
            // Strategy Patterns
            clsStreetRacer streetRacer = new clsStreetRacer();
            clsHelicopter helicopter = new clsHelicopter();
            clsFormulaOne formulaone = new clsFormulaOne();
            clsJet jet = new clsJet();
                        
            streetRacer.go();
            formulaone.go();
            helicopter.go();    
        
            Console.ReadLine();
        
        } 
        


Kết quả đúng như mong đợi. Tuy nhiên bây giờ bạn đã sử dụng mối quan hệ “has-a” thay vì quan hệ kế thừa “is-a”. Từ lúc này bạn có thể sử dụng các thuật toán xuyên suốt chương trình, bất cứ đâu, vì nó đã không còn nằm trong các lớp StreetRacer hay Helicopter nữa.

Kỹ thuật này thay thế cho cách tạo các lớp con và sử dụng kế thừa. Nếu bạn sử dụng một quan hệ kế thừa “is-a”, bạn sẽ bắt đầu sự rắc rối cho việc kiểm soát được các phương thức trong lớp cơ sở và các lớp con – trong ví dụ là bạn phải nạp đè lên phương thức go cho lớp HelicopterJet. Nếu bạn sử dụng mô hình “has-a”, bạn có thể tạo ra một dòng họ các thuật toán một cách rõ ràng, và sau đó bạn chọn một thuật toán thích hợp để sử dụng.

Theo cách này, bạn đã có thể khắc phục được vấn đề mà sự kế thừa đã gây ra cho hầu hết các lập trình viên: nếu bạn phải giải quyết một chức năng cụ thể nào đó qua nhiều thế hệ của một lớp, và chức năng này liên tục thay đổi, bạn sẽ phải chỉnh sửa rất nhiều mã của mình. Mặt khác, khi bạn tập trung chức năng đó vào một thuật toán duy nhất, việc thay đổi nó sẽ dễ dàng hơn rất nhiều.

Quay lại ví dụ trên, khi ban giám đốc muốn thay đổi từ “Now I’m flying” sang “Now I’m flying at 20 mph”. Đơn giản, bạn chỉ cần chỉnh sửa thuật toán GoByFlying:


public class clsGoByFlyingAlgorithm:IGoAlgorithm
        {
                public void go()
                {
                    Console.WriteLine("Now, I'm Flying at 200 mph!");
                }
         }
        

Và bây giờ tất cả mã của bạn đã tự động được cập nhật, bạn không cần thiết phải đi tìm và chỉnh sửa từng lớp con như trước nữa. Theo cách này, bạn đã tập trung sự xử lý một chức năng vào một đối tượng thuật toán duy nhất, bạn sẽ dễ dàng quản lý đối tượng này trong trường hợp yêu cầu chức năng bị thay đổi.


“Đợi một chút,” Giám đốc MegaGigaCo nói. “Có việc xảy ra, máy bay phản lực không chỉ bay nhanh, đầu tiên nó chạy trên đường băng một lúc, và khi đáp xuống mặt đất, nó lại tiếp tục chạy trên đường băng nữa. Vì vậy chúng ta phải chỉnh sửa chức năng cho nó lại : đầu tiên là chạy trên đường băng, rồi bay, rồi chạy tiếp?”
“Đó là về mặt lý thuyết,” các lập trình viên rên rỉ “Nhưng điều đó làm chúng ta phải viết thêm nhiều đoạn mã nữa”
“Không sao cả” Bạn nói. “Đó là một trong những điểm kỳ diệu của việc sử dụng một đối tượng thuật toán bên ngoài. Bạn có thể thay đổi nó khi bạn thực thi chương trình”
Khi bạn viết mã cho một chức năng trong một lớp, bạn không thể thay đổi nó khi thực thi chương trình. Tuy nhiên khi bạn sử dụng một đối tượng thuật toán bên ngoài với mối quan hệ “has-a”, bạn dễ dàng thay đổi chức năng đó lúc chương trình hoạt động. Nói cách khác một quan hệ “has-a” cho phép bạn dễ dàng thay đổi hơn một quan hệ “is-a” đặc biệt khi chương trình đang hoạt động.
Và đây là ví dụ cho việc sử dụng linh hoạt các thuật toán, cũng như việc thay đổi nó khi chương trình đang chạy. Bạn có thể tạo một máy ban phản lực, có thể chạy trên đường băng với thuật toán GoByDrivingAlgorithm,

Bạn có thể cài đặt thuật toán mới setGoAlgorithm cho máy bay phản lực, để thay đổi phương thức go một cách linh động, và sau đó gọi lại phương thức go để thấy sự khác biệt.


static void Main(string[] args)
        {
            // Strategy Patterns
            clsStreetRacer streetRacer = new clsStreetRacer();
            clsHelicopter helicopter = new clsHelicopter();
            clsFormulaOne formulaone = new clsFormulaOne();
            clsJet jet = new clsJet();
                        
            streetRacer.go();
            formulaone.go();
            helicopter.go();
        
        
            jet.setGoAlgorithm(new clsGoByDrivingAlgorithm());
            jet.go();
            jet.setGoAlgorithm(new clsGoByFlyingFastAlgorithm());
            jet.go();
            jet.setGoAlgorithm(new clsGoByDrivingAlgorithm());
            jet.go();
            
        
            Console.ReadLine();
        
        } 


Bạn thấy đó, việc chuyển đổi một thuật toán lúc thực thi chương trình rất dễ dàng. Nói cách khác, nếu bạn để việc xử lý thuật toán vào nội tại một lớp, bạn sẽ không thể thay đổi nó lúc chạy chương trình. Nhưng khi bạn cài đặt một chiến lược “Strategy”, bạn sẽ dễ dàng thay đổi nó khi chạy chương trình. Tất cả những điều trên mang chúng ta đến một mẫu thiết kế “Strategy”, hay được gọi là mẫu “chiến lược”.


Kết luận

MẪU “STRATEGY” – Mẫu chiến lược


Ý nghĩa thực sự của mẫu chiến lược là bạn tách rời phần xử lý một chức năng cụ thể ra khỏi đối tượng của bạn. Sau đó tạo ra một tập hợp các thuật toán để xử lý chức năng đó và lựa chọn thuật toán nào mà bạn thấy đúng đắn nhất khi thực thi chương trình. Mẫu thiết kế này thường được sử dụng để thay thế cho sự kế thừa, khi bạn muốn chấm dứt việc theo dõi và chỉnh sửa một chức năng qua nhiều lớp con.
Chúng ta có thể nhìn thấy vấn đề tổng quát như sau. Đầu tiên mọi việc đều ổn, bạn có một đối tượng, một chức năng

Strategy Pattern


Một thời gian sau đó, do yêu cầu đặc biệt, bạn cần có thêm một lớp mới, bạn kế thừa lớp cũ, và ghi đè lên phương thức đã được thừa hưởng. Bạn đang dàn trải việc xử lý chức năng qua nhiều lớp con như hình:

Strategy Pattern



Mẫu “Strategy”, mẫu chiến lược nói rằng: bạn cần phải tách những phần dễ thay đổi và đóng gói chúng vào các đối tượng và bạn có thể sử dụng các đối tượng này khi cần. Bây giờ bạn có thể chỉnh sửa mã của mình thông qua việc tạo sự “kết hợp” các đối tượng. Khi chương trình thực thi, bạn chỉ cần sử dụng đúng đối tượng mà bạn cần. Như hình sau:

Strategy Pattern




Gợi ý: Bạn nên sử dụng mẫu Strategy khi có những tình huống sau:
  • Bạn có một đoạn mã dễ thay đổi, và bạn tách chúng ra khỏi chương trình chính để dễ dàng bảo trì
  • Bạn muốn tránh sự rắc rối, khi phải hiện thực một chức năng nào đó qua quá nhiều lớp con.
  • Bạn muốn thay đổi thuật toán sử dụng khi chạy chương trình



ref: 
https://sourcemaking.com/design_patterns/strategy
https://haihth.wordpress.com/2013/02/21/dp-chapter2/

🙇🏼🙇🏼 We Appreciate Your Comments and Suggestions - Webzone, all things Tech Tips web development
Popular Webzone Tech Tips topic maybe you will be like it - by Webzone Tech Tips - Zidane
As a student, I found Blogspot very useful when I joined in 2014. I have been a developer for years . To give back and share what I learned, I started Webzone, a blog with tech tips. You can also search for tech tips zidane on Google and find my helpful posts. Love you all,

I am glad you visited my blog. I hope you find it useful for learning tech tips and webzone tricks. If you have any technical issues, feel free to browse my posts and see if they can help you solve them. You can also leave a comment or contact me if you need more assistance. Here is my blog address: https://learn-tech-tips.blogspot.com.

My blog where I share my passion for web development, webzone design, and tech tips. You will find tutorials on how to build websites from scratch, using hot trends frameworks like nestjs, nextjs, cakephp, devops, docker, and more. You will also learn how to fix common bugs on development, like a mini stackoverflow. Plus, you will discover how to easily learn programming languages such as PHP (CAKEPHP, LARAVEL), C#, C++, Web(HTML, CSS, javascript), and other useful things like Office (Excel, Photoshop). I hope you enjoy my blog and find it helpful for your projects. :)

Thanks and Best Regards!
Follow me on Tiktok @learntechtips and send me a direct message. I will be happy to chat with you.
Webzone - Zidane (huuvi168@gmail.com)
I'm developer, I like code, I like to learn new technology and want to be friend with people for learn each other
I'm a developer who loves coding, learning new technologies, and making friends with people who share the same passion. I have been a full stack developer since 2015, with more than years of experience in web development.
Copyright @2022(November) Version 1.0.0 - By Webzone, all things Tech Tips for Web Development Zidane
https://learn-tech-tips.blogspot.com