### Execution Output of Facade Example Source: https://refactoringguru.cn/design-patterns/facade/php/example The expected console output when running the YouTubeDownloader facade example. ```text Fetching video metadata from youtube... Saving video file to a temporary file... Processing source video... Normalizing and resizing the video to smaller dimensions... Capturing preview image... Saving video in target formats... Done! ``` -------------------------------- ### Example Output Source: https://refactoringguru.cn/design-patterns/abstract-factory/rust/example Expected output when running the application. ```text Windows button has pressed Windows button has pressed Windows checkbox has switched Windows checkbox has switched ``` -------------------------------- ### Execution Output of Template Method Example Source: https://refactoringguru.cn/design-patterns/template-method/php/example Shows the console output when running the social network posting example. ```text Username: > neo Password: > 123123 Message: > What is the Matrix? Choose the social network to post the message: 1 - Facebook 2 - Twitter > 1 Checking user's credentials... Name: neo Password: ****** ..... Facebook: 'neo' has logged in successfully. Facebook: 'neo' has posted 'What is the Matrix?'. Facebook: 'neo' has been logged out. ``` -------------------------------- ### State Pattern Usage Demonstration Source: https://refactoringguru.cn/design-patterns/state/php/example Example usage showing how to initialize an invoice and perform state transitions, including error handling for invalid transitions. ```php try { echo "=== Invoice State Pattern Demo ===\n\n"; // Create a new invoice (starts in draft state) $invoice = new Invoice(1001, 1500.00); echo "Created invoice: " . json_encode($invoice->getInfo()) . "\n\n"; // Scenario 1: Draft -> Open -> Paid echo "--- Scenario 1: Draft -> Open -> Paid ---\n"; $invoice->finalize(); // Draft -> Open echo "Current state: " . $invoice->getStateName() . "\n"; $invoice->pay(); // Open -> Paid echo "Current state: " . $invoice->getStateName() . "\n"; // Try to pay again (should fail) try { $invoice->pay(); } catch (InvalidStateTransitionException $e) { echo "Expected error: " . $e->getMessage() . "\n"; } echo "\n--- Scenario 2: Draft -> Open -> Void ---\n"; $invoice2 = new Invoice(1002, 750.00); $invoice2->finalize(); // Draft -> Open $invoice2->void(); // Open -> Void echo "Invoice 2 state: " . $invoice2->getStateName() . "\n"; ``` -------------------------------- ### Execution Output of Command Pattern Example Source: https://refactoringguru.cn/design-patterns/command/swift/example Displays the console output generated by the Command pattern implementation, showing the sequence of actions and cancellations. ```text User: Hey Siri, I am leaving my home Siri: performing leaveHome-action User: Hey Siri, I am leaving my work in 3 minutes Siri: performing leaveWork-action User: Hey Siri, I am still working Siri: canceling leaveWork-action DoorOperation: Doors are closed via HomeKit. WindowOperation: Windows are closed via HomeKit. TaxiOperation: operation is canceled ``` -------------------------------- ### Client Usage Demonstration Source: https://refactoringguru.cn/design-patterns/memento/php/example Demonstrates initializing the configuration manager, performing updates, and utilizing the history manager for undo operations. ```php echo "=== Configuration Manager with Memento Pattern Demo ===\n\n"; /** * Example 1: Basic configuration management with backup/restore */ echo "--- Example 1: Basic Configuration Management ---\n"; // Initialize configuration manager with default settings $config = new ConfigManager([ 'maintenance_mode' => false, 'theme' => 'light', 'seo' => ['title' => 'My Website', 'description' => 'Welcome to my site!'], 'debug' => false, 'max_users' => 1000 ]); // Create history manager $history = new ConfigHistory($config); echo "\nInitial configuration:\n"; print_r($config->getConfig()); /** * Example 2: Making changes with backups */ echo "\n--- Example 2: Making Changes with Backups ---\n"; // Create backup before making changes $history->backup(); // Update theme settings $config->updateConfig([ 'theme' => 'dark', 'theme_options' => ['sidebar' => 'collapsed', 'font_size' => 'large'] ]); echo "\nAfter theme update:\n"; print_r($config->getConfig()); // Create another backup $history->backup(); // Enable maintenance mode $config->enableMaintenanceMode(); echo "\nAfter enabling maintenance mode:\n"; print_r($config->getConfig()); /** * Example 3: Demonstrating undo functionality */ echo "\n--- Example 3: Undo Functionality ---\n"; // Show current history $history->showHistory(); // Undo last change (maintenance mode) echo "Undoing maintenance mode activation...\n"; $history->undo(); echo "\nAfter first undo:\n"; print_r($config->getConfig()); // Undo theme changes echo "\nUndoing theme changes...\n"; $history->undo(); echo "\nAfter second undo (back to original):\n"; print_r($config->getConfig()); /** * Example 4: Multiple configuration scenarios */ echo "\n--- Example 4: Multiple Configuration Scenarios ---\n"; ``` -------------------------------- ### Configure and Run Application Source: https://refactoringguru.cn/design-patterns/abstract-factory/java/example Demonstrates runtime selection of the factory based on environment configuration. ```java package refactoring_guru.abstract_factory.example; import refactoring_guru.abstract_factory.example.app.Application; import refactoring_guru.abstract_factory.example.factories.GUIFactory; import refactoring_guru.abstract_factory.example.factories.MacOSFactory; import refactoring_guru.abstract_factory.example.factories.WindowsFactory; /** * Demo class. Everything comes together here. */ public class Demo { /** * Application picks the factory type and creates it in run time (usually at * initialization stage), depending on the configuration or environment * variables. */ private static Application configureApplication() { Application app; GUIFactory factory; String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("mac")) { factory = new MacOSFactory(); } else { factory = new WindowsFactory(); } app = new Application(factory); return app; } public static void main(String[] args) { Application app = configureApplication(); app.paint(); } } ``` -------------------------------- ### Main Entry Point Source: https://refactoringguru.cn/design-patterns/builder/cpp/example Initializes the director and executes the client code. ```cpp int main(){ Director* director= new Director(); ClientCode(*director); delete director; return 0; } ``` -------------------------------- ### Initialize Proxy Demo Source: https://refactoringguru.cn/design-patterns/proxy/java/example The main entry point that compares the performance of a naive downloader against one using the caching proxy. ```java package refactoring_guru.proxy.example; import refactoring_guru.proxy.example.downloader.YouTubeDownloader; import refactoring_guru.proxy.example.proxy.YouTubeCacheProxy; import refactoring_guru.proxy.example.some_cool_media_library.ThirdPartyYouTubeClass; public class Demo { public static void main(String[] args) { YouTubeDownloader naiveDownloader = new YouTubeDownloader(new ThirdPartyYouTubeClass()); YouTubeDownloader smartDownloader = new YouTubeDownloader(new YouTubeCacheProxy()); long naive = test(naiveDownloader); long smart = test(smartDownloader); System.out.print("Time saved by caching proxy: " + (naive - smart) + "ms"); } private static long test(YouTubeDownloader downloader) { long startTime = System.currentTimeMillis(); // User behavior in our app: downloader.renderPopularVideos(); downloader.renderVideoPage("catzzzzzzzzz"); downloader.renderPopularVideos(); downloader.renderVideoPage("dancesvideoo"); // Users might visit the same page quite often. downloader.renderVideoPage("catzzzzzzzzz"); downloader.renderVideoPage("someothervid"); long estimatedTime = System.currentTimeMillis() - startTime; System.out.print("Time elapsed: " + estimatedTime + "ms\n"); return estimatedTime; } } ``` -------------------------------- ### Execution Output of Abstract Factory Source: https://refactoringguru.cn/design-patterns/abstract-factory/typescript/example The console output generated by running the TypeScript example. ```text Client: Testing client code with the first factory type... The result of the product B1. The result of the B1 collaborating with the (The result of the product A1.) Client: Testing the same client code with the second factory type... The result of the product B2. The result of the B2 collaborating with the (The result of the product A2.) ``` -------------------------------- ### Factory Method Execution Output Source: https://refactoringguru.cn/design-patterns/factory-method/swift/example The console output resulting from the execution of the Factory Method example. ```text Info is presented over Wifi: Very important info of the presentation Info is presented over Bluetooth: Very important info of the presentation ``` -------------------------------- ### Demo Class Initialization Source: https://refactoringguru.cn/design-patterns/state/java/example Entry point for the application that initializes the player and the UI. ```java package refactoring_guru.state.example; import refactoring_guru.state.example.ui.Player; import refactoring_guru.state.example.ui.UI; /** * Demo class. Everything comes together here. */ public class Demo { public static void main(String[] args) { Player player = new Player(); UI ui = new UI(player); ui.init(); } } ``` -------------------------------- ### Demo Initialization Source: https://refactoringguru.cn/design-patterns/mediator/java/example Main entry point that registers components with the mediator and launches the GUI. ```java package refactoring_guru.mediator.example; import refactoring_guru.mediator.example.components.*; import refactoring_guru.mediator.example.mediator.Editor; import refactoring_guru.mediator.example.mediator.Mediator; import javax.swing.*; /** * Demo class. Everything comes together here. */ public class Demo { public static void main(String[] args) { Mediator mediator = new Editor(); mediator.registerComponent(new Title()); mediator.registerComponent(new TextBox()); mediator.registerComponent(new AddButton()); mediator.registerComponent(new DeleteButton()); mediator.registerComponent(new SaveButton()); mediator.registerComponent(new List(new DefaultListModel())); mediator.registerComponent(new Filter()); mediator.createGUI(); } } ``` -------------------------------- ### Decorator Pattern Execution Output Source: https://refactoringguru.cn/design-patterns/decorator/csharp/example Displays the console output resulting from the execution of the conceptual example. ```text Client: I get a simple component: RESULT: ConcreteComponent Client: Now I've got a decorated component: RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent)) ``` -------------------------------- ### Define CarType enumeration Source: https://refactoringguru.cn/design-patterns/builder/java/example Defines the available types of cars used within the builder example. ```java package refactoring_guru.builder.example.cars; public enum CarType { CITY_CAR, SPORTS_CAR, SUV } ``` -------------------------------- ### Execution Output for Template Method Example Source: https://refactoringguru.cn/design-patterns/template-method/swift/example Displays the console output generated by the permission accessor implementation. ```text You have access to Camera You have access to Microphone PhotoLibrary Accessor: Rejected with access. Updating analytics... You do not have access to PhotoLibrary ``` -------------------------------- ### Client Code for Builder Pattern Source: https://refactoringguru.cn/design-patterns/builder/cpp/example Demonstrates how to use a director to build products and how to manually construct a custom product without a director. ```cpp void ClientCode(Director& director) { ConcreteBuilder1* builder = new ConcreteBuilder1(); director.set_builder(builder); std::cout << "Standard basic product:\n"; director.BuildMinimalViableProduct(); Product1* p= builder->GetProduct(); p->ListParts(); delete p; std::cout << "Standard full featured product:\n"; director.BuildFullFeaturedProduct(); p= builder->GetProduct(); p->ListParts(); delete p; // Remember, the Builder pattern can be used without a Director class. std::cout << "Custom product:\n"; builder->ProducePartA(); builder->ProducePartC(); p=builder->GetProduct(); p->ListParts(); delete p; delete builder; } ``` -------------------------------- ### Execution Output Source: https://refactoringguru.cn/design-patterns/proxy/php/example Shows the console output when running the proxy example, demonstrating cache hits and misses. ```text Executing client code with real subject: Downloading a file from the Internet. Downloaded bytes: 1270 Downloading a file from the Internet. Downloaded bytes: 1270 Executing the same client code with a proxy: CacheProxy MISS. Downloading a file from the Internet. Downloaded bytes: 1270 CacheProxy HIT. Retrieving result from cache. ``` -------------------------------- ### Configure and Execute Chain of Responsibility Demo Source: https://refactoringguru.cn/design-patterns/chain-of-responsibility/java/example The Demo class initializes the server and links various middleware components to process login requests. ```java package refactoring_guru.chain_of_responsibility.example; import refactoring_guru.chain_of_responsibility.example.middleware.Middleware; import refactoring_guru.chain_of_responsibility.example.middleware.RoleCheckMiddleware; import refactoring_guru.chain_of_responsibility.example.middleware.ThrottlingMiddleware; import refactoring_guru.chain_of_responsibility.example.middleware.UserExistsMiddleware; import refactoring_guru.chain_of_responsibility.example.server.Server; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * Demo class. Everything comes together here. */ public class Demo { private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); private static Server server; private static void init() { server = new Server(); server.register("admin@example.com", "admin_pass"); server.register("user@example.com", "user_pass"); // All checks are linked. Client can build various chains using the same // components. Middleware middleware = Middleware.link( new ThrottlingMiddleware(2), new UserExistsMiddleware(server), new RoleCheckMiddleware() ); // Server gets a chain from client code. server.setMiddleware(middleware); } public static void main(String[] args) throws IOException { init(); boolean success; do { System.out.print("Enter email: "); String email = reader.readLine(); System.out.print("Input password: "); String password = reader.readLine(); success = server.logIn(email, password); } while (!success); } } ``` -------------------------------- ### Fluent Interface Example Source: https://refactoringguru.cn/design-patterns/builder/rust/example Demonstrates method chaining for object construction, which is distinct from the formal Builder pattern. ```rust let car = Car::default().places(5).gas(30) ``` -------------------------------- ### Execute Proxy Pattern Source: https://refactoringguru.cn/design-patterns/proxy/rust/example Main entry point demonstrating the proxy handling requests and enforcing rate limits. ```rust mod server; use crate::server::{NginxServer, Server}; fn main() { let app_status = &"/app/status".to_string(); let create_user = &"/create/user".to_string(); let mut nginx = NginxServer::new(); let (code, body) = nginx.handle_request(app_status, "GET"); println!("Url: {}\nHttpCode: {}\nBody: {}\n", app_status, code, body); let (code, body) = nginx.handle_request(app_status, "GET"); println!("Url: {}\nHttpCode: {}\nBody: {}\n", app_status, code, body); let (code, body) = nginx.handle_request(app_status, "GET"); println!("Url: {}\nHttpCode: {}\nBody: {}\n", app_status, code, body); let (code, body) = nginx.handle_request(create_user, "POST"); println!("Url: {}\nHttpCode: {}\nBody: {}\n", create_user, code, body); let (code, body) = nginx.handle_request(create_user, "GET"); println!("Url: {}\nHttpCode: {}\nBody: {}\n", create_user, code, body); } ``` -------------------------------- ### Bridge Pattern Execution Output Source: https://refactoringguru.cn/design-patterns/bridge/csharp/example The expected console output when running the conceptual Bridge pattern example. ```text Abstract: Base operation with: ConcreteImplementationA: The result in platform A. ExtendedAbstraction: Extended operation with: ConcreteImplementationA: The result in platform B. ``` -------------------------------- ### Execution Output of Flyweight Example Source: https://refactoringguru.cn/design-patterns/flyweight/swift/example Shows the console output verifying that appearance objects are cached and reused after the first creation. ```text Client: I created a number of objects to display Client: Let's show animals for the 1st time AppearanceFactory: Can't find a cached cat-object, creating a new one. Cell: Updating an appearance of a cat-cell: photos 1 AppearanceFactory: Reusing an existing cat-appearance. Cell: Updating an appearance of a cat-cell: photos 1 AppearanceFactory: Can't find a cached dog-object, creating a new one. Cell: Updating an appearance of a dog-cell: photos 2 Client: I have a new dog, let's show it the same way! AppearanceFactory: Reusing an existing dog-appearance. Cell: Updating an appearance of a dog-cell: photos 2 ``` -------------------------------- ### Implement Memento Pattern in C++ Source: https://refactoringguru.cn/design-patterns/memento/cpp/example This example demonstrates the interaction between the Originator, ConcreteMemento, and Caretaker classes to perform state backups and rollbacks. ```cpp /** * The Memento interface provides a way to retrieve the memento's metadata, such * as creation date or name. However, it doesn't expose the Originator's state. */ class Memento { public: virtual ~Memento() {} virtual std::string GetName() const = 0; virtual std::string date() const = 0; virtual std::string state() const = 0; }; /** * The Concrete Memento contains the infrastructure for storing the Originator's * state. */ class ConcreteMemento : public Memento { private: std::string state_; std::string date_; public: ConcreteMemento(std::string state) : state_(state) { this->state_ = state; std::time_t now = std::time(0); this->date_ = std::ctime(&now); } /** * The Originator uses this method when restoring its state. */ std::string state() const override { return this->state_; } /** * The rest of the methods are used by the Caretaker to display metadata. */ std::string GetName() const override { return this->date_ + " / (" + this->state_.substr(0, 9) + "...)"; } std::string date() const override { return this->date_; } }; /** * The Originator holds some important state that may change over time. It also * defines a method for saving the state inside a memento and another method for * restoring the state from it. */ class Originator { /** * @var string For the sake of simplicity, the originator's state is stored * inside a single variable. */ private: std::string state_; std::string GenerateRandomString(int length = 10) { const char alphanum[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; int stringLength = sizeof(alphanum) - 1; std::string random_string; for (int i = 0; i < length; i++) { random_string += alphanum[std::rand() % stringLength]; } return random_string; } public: Originator(std::string state) : state_(state) { std::cout << "Originator: My initial state is: " << this->state_ << "\n"; } /** * The Originator's business logic may affect its internal state. Therefore, * the client should backup the state before launching methods of the business * logic via the save() method. */ void DoSomething() { std::cout << "Originator: I'm doing something important.\n"; this->state_ = this->GenerateRandomString(30); std::cout << "Originator: and my state has changed to: " << this->state_ << "\n"; } /** * Saves the current state inside a memento. */ Memento *Save() { return new ConcreteMemento(this->state_); } /** * Restores the Originator's state from a memento object. */ void Restore(Memento *memento) { this->state_ = memento->state(); std::cout << "Originator: My state has changed to: " << this->state_ << "\n"; delete memento; } }; /** * The Caretaker doesn't depend on the Concrete Memento class. Therefore, it * doesn't have access to the originator's state, stored inside the memento. It * works with all mementos via the base Memento interface. */ class Caretaker { /** * @var Memento[] */ private: std::vector mementos_; /** * @var Originator */ Originator *originator_; public: Caretaker(Originator* originator) : originator_(originator) { } ~Caretaker() { for (auto m : mementos_) delete m; } void Backup() { std::cout << "\nCaretaker: Saving Originator's state...\n"; this->mementos_.push_back(this->originator_->Save()); } void Undo() { if (!this->mementos_.size()) { return; } Memento *memento = this->mementos_.back(); this->mementos_.pop_back(); std::cout << "Caretaker: Restoring state to: " << memento->GetName() << "\n"; try { this->originator_->Restore(memento); } catch (...) { this->Undo(); } } void ShowHistory() const { std::cout << "Caretaker: Here's the list of mementos:\n"; for (Memento *memento : this->mementos_) { std::cout << memento->GetName() << "\n"; } } }; /** * Client code. */ void ClientCode() { Originator *originator = new Originator("Super-duper-super-puper-super."); Caretaker *caretaker = new Caretaker(originator); caretaker->Backup(); originator->DoSomething(); caretaker->Backup(); originator->DoSomething(); caretaker->Backup(); originator->DoSomething(); std::cout << "\n"; caretaker->ShowHistory(); std::cout << "\nClient: Now, let's rollback!\n\n"; caretaker->Undo(); std::cout << "\nClient: Once more!\n\n"; caretaker->Undo(); delete originator; delete caretaker; } int main() { std::srand(static_cast(std::time(NULL))); ClientCode(); return 0; } ``` -------------------------------- ### Implement Client Demo for Strategy Pattern Source: https://refactoringguru.cn/design-patterns/strategy/java/example The Demo class acts as the client, selecting a concrete payment strategy at runtime based on user input and executing the order process. ```java package refactoring_guru.strategy.example; import refactoring_guru.strategy.example.order.Order; import refactoring_guru.strategy.example.strategies.PayByCreditCard; import refactoring_guru.strategy.example.strategies.PayByPayPal; import refactoring_guru.strategy.example.strategies.PayStrategy; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; /** * World first console e-commerce application. */ public class Demo { private static Map priceOnProducts = new HashMap<>(); private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); private static Order order = new Order(); private static PayStrategy strategy; static { priceOnProducts.put(1, 2200); priceOnProducts.put(2, 1850); priceOnProducts.put(3, 1100); priceOnProducts.put(4, 890); } public static void main(String[] args) throws IOException { while (!order.isClosed()) { int cost; String continueChoice; do { System.out.print("Please, select a product:" + "\n" + "1 - Mother board" + "\n" + "2 - CPU" + "\n" + "3 - HDD" + "\n" + "4 - Memory" + "\n"); int choice = Integer.parseInt(reader.readLine()); cost = priceOnProducts.get(choice); System.out.print("Count: "); int count = Integer.parseInt(reader.readLine()); order.setTotalCost(cost * count); System.out.print("Do you wish to continue selecting products? Y/N: "); continueChoice = reader.readLine(); } while (continueChoice.equalsIgnoreCase("Y")); if (strategy == null) { System.out.println("Please, select a payment method:" + "\n" + "1 - PalPay" + "\n" + "2 - Credit Card"); String paymentMethod = reader.readLine(); // Client creates different strategies based on input from user, // application configuration, etc. if (paymentMethod.equals("1")) { strategy = new PayByPayPal(); } else { strategy = new PayByCreditCard(); } } // Order object delegates gathering payment data to strategy object, // since only strategies know what data they need to process a // payment. order.processOrder(strategy); System.out.print("Pay " + order.getTotalCost() + " units or Continue shopping? P/C: "); String proceed = reader.readLine(); if (proceed.equalsIgnoreCase("P")) { // Finally, strategy handles the payment. if (strategy.pay(order.getTotalCost())) { System.out.println("Payment has been successful."); } else { System.out.println("FAIL! Please, check your data."); } order.setClosed(); } } } } ``` -------------------------------- ### Flyweight Pattern Conceptual Implementation in C# Source: https://refactoringguru.cn/design-patterns/flyweight/csharp/example This example demonstrates the Flyweight, FlyweightFactory, and Car classes. It requires the Json.NET library for serialization. ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; // Use Json.NET library, you can download it from NuGet Package Manager namespace RefactoringGuru.DesignPatterns.Flyweight.Conceptual { // The Flyweight stores a common portion of the state (also called intrinsic // state) that belongs to multiple real business entities. The Flyweight // accepts the rest of the state (extrinsic state, unique for each entity) // via its method parameters. public class Flyweight { private Car _sharedState; public Flyweight(Car car) { this._sharedState = car; } public void Operation(Car uniqueState) { string s = JsonSerializer.Serialize(this._sharedState); string u = JsonSerializer.Serialize(uniqueState); Console.WriteLine($"Flyweight: Displaying shared {s} and unique {u} state."); } } // The Flyweight Factory creates and manages the Flyweight objects. It // ensures that flyweights are shared correctly. When the client requests a // flyweight, the factory either returns an existing instance or creates a // new one, if it doesn't exist yet. public class FlyweightFactory { private List> flyweights = new List>(); public FlyweightFactory(params Car[] args) { foreach (var elem in args) { flyweights.Add(new Tuple(new Flyweight(elem), this.getKey(elem))); } } // Returns a Flyweight's string hash for a given state. public string getKey(Car key) { List elements = new List(); elements.Add(key.Model); elements.Add(key.Color); elements.Add(key.Company); if (key.Owner != null && key.Number != null) { elements.Add(key.Number); elements.Add(key.Owner); } elements.Sort(); return string.Join("_", elements); } // Returns an existing Flyweight with a given state or creates a new // one. public Flyweight GetFlyweight(Car sharedState) { string key = this.getKey(sharedState); if (flyweights.Where(t => t.Item2 == key).Count() == 0) { Console.WriteLine("FlyweightFactory: Can't find a flyweight, creating new one."); this.flyweights.Add(new Tuple(new Flyweight(sharedState), key)); } else { Console.WriteLine("FlyweightFactory: Reusing existing flyweight."); } return this.flyweights.Where(t => t.Item2 == key).FirstOrDefault().Item1; } public void listFlyweights() { var count = flyweights.Count; Console.WriteLine($"\nFlyweightFactory: I have {count} flyweights:"); foreach (var flyweight in flyweights) { Console.WriteLine(flyweight.Item2); } } } public class Car { public string Owner { get; set; } public string Number { get; set; } public string Company { get; set; } public string Model { get; set; } public string Color { get; set; } } class Program { static void Main(string[] args) { // The client code usually creates a bunch of pre-populated // flyweights in the initialization stage of the application. var factory = new FlyweightFactory( new Car { Company = "Chevrolet", Model = "Camaro2018", Color = "pink" }, new Car { Company = "Mercedes Benz", Model = "C300", Color = "black" }, new Car { Company = "Mercedes Benz", Model = "C500", Color = "red" }, new Car { Company = "BMW", Model = "M5", Color = "red" }, new Car { Company = "BMW", Model = "X6", Color = "white" } ); factory.listFlyweights(); addCarToPoliceDatabase(factory, new Car { Number = "CL234IR", Owner = "James Doe", Company = "BMW", Model = "M5", Color = "red" }); ``` -------------------------------- ### Builder Pattern Client Implementation in C# Source: https://refactoringguru.cn/design-patterns/builder/csharp/example Demonstrates how to use a Director to build products or construct them manually using the builder instance. ```csharp class Program { static void Main(string[] args) { // The client code creates a builder object, passes it to the // director and then initiates the construction process. The end // result is retrieved from the builder object. var director = new Director(); var builder = new ConcreteBuilder(); director.Builder = builder; Console.WriteLine("Standard basic product:"); director.BuildMinimalViableProduct(); Console.WriteLine(builder.GetProduct().ListParts()); Console.WriteLine("Standard full featured product:"); director.BuildFullFeaturedProduct(); Console.WriteLine(builder.GetProduct().ListParts()); // Remember, the Builder pattern can be used without a Director // class. Console.WriteLine("Custom product:"); builder.BuildPartA(); builder.BuildPartC(); Console.Write(builder.GetProduct().ListParts()); } } ``` -------------------------------- ### View Execution Output Source: https://refactoringguru.cn/design-patterns/chain-of-responsibility/java/example Sample output demonstrating the behavior of the middleware chain during login attempts. ```text Enter email: admin@example.com Input password: admin_pass Hello, admin! Authorization have been successful! Enter email: wrong@example.com Input password: wrong_pass This email is not registered! Enter email: wrong@example.com Input password: wrong_pass This email is not registered! Enter email: wrong@example.com Input password: wrong_pass Request limit exceeded! ``` -------------------------------- ### Mediator Pattern Implementation in Swift Source: https://refactoringguru.cn/design-patterns/mediator/swift/example This example defines a ScreenMediator that implements the ScreenUpdatable protocol to broadcast news updates to registered view controllers. ```swift import XCTest class MediatorRealWorld: XCTestCase { func test() { let newsArray = [News(id: 1, title: "News1", likesCount: 1), News(id: 2, title: "News2", likesCount: 2)] let numberOfGivenLikes = newsArray.reduce(0, { $0 + $1.likesCount }) let mediator = ScreenMediator() let feedVC = NewsFeedViewController(mediator, newsArray) let newsDetailVC = NewsDetailViewController(mediator, newsArray.first!) let profileVC = ProfileViewController(mediator, numberOfGivenLikes) mediator.update([feedVC, newsDetailVC, profileVC]) feedVC.userLikedAllNews() feedVC.userDislikedAllNews() } } class NewsFeedViewController: ScreenUpdatable { private var newsArray: [News] private weak var mediator: ScreenUpdatable? init(_ mediator: ScreenUpdatable?, _ newsArray: [News]) { self.newsArray = newsArray self.mediator = mediator } func likeAdded(to news: News) { print("News Feed: Received a liked news model with id \(news.id)") for var item in newsArray { if item == news { item.likesCount += 1 } } } func likeRemoved(from news: News) { print("News Feed: Received a disliked news model with id \(news.id)") for var item in newsArray { if item == news { item.likesCount -= 1 } } } func userLikedAllNews() { print("\n\nNews Feed: User LIKED all news models") print("News Feed: I am telling to mediator about it...\n") newsArray.forEach({ mediator?.likeAdded(to: $0) }) } func userDislikedAllNews() { print("\n\nNews Feed: User DISLIKED all news models") print("News Feed: I am telling to mediator about it...\n") newsArray.forEach({ mediator?.likeRemoved(from: $0) }) } } class NewsDetailViewController: ScreenUpdatable { private var news: News private weak var mediator: ScreenUpdatable? init(_ mediator: ScreenUpdatable?, _ news: News) { self.news = news self.mediator = mediator } func likeAdded(to news: News) { print("News Detail: Received a liked news model with id \(news.id)") if self.news == news { self.news.likesCount += 1 } } func likeRemoved(from news: News) { print("News Detail: Received a disliked news model with id \(news.id)") if self.news == news { self.news.likesCount -= 1 } } } class ProfileViewController: ScreenUpdatable { private var numberOfGivenLikes: Int private weak var mediator: ScreenUpdatable? init(_ mediator: ScreenUpdatable?, _ numberOfGivenLikes: Int) { self.numberOfGivenLikes = numberOfGivenLikes self.mediator = mediator } func likeAdded(to news: News) { print("Profile: Received a liked news model with id \(news.id)") numberOfGivenLikes += 1 } func likeRemoved(from news: News) { print("Profile: Received a disliked news model with id \(news.id)") numberOfGivenLikes -= 1 } } protocol ScreenUpdatable: class { func likeAdded(to news: News) func likeRemoved(from news: News) } class ScreenMediator: ScreenUpdatable { private var screens: [ScreenUpdatable]? func update(_ screens: [ScreenUpdatable]) { self.screens = screens } func likeAdded(to news: News) { print("Screen Mediator: Received a liked news model with id \(news.id)") screens?.forEach({ $0.likeAdded(to: news) }) } func likeRemoved(from news: News) { print("ScreenMediator: Received a disliked news model with id \(news.id)") screens?.forEach({ $0.likeRemoved(from: news) }) } } struct News: Equatable { let id: Int let title: String var likesCount: Int /// Other properties static func == (left: News, right: News) -> Bool { return left.id == right.id } } ``` -------------------------------- ### 实现责任链模式 (main.py) Source: https://refactoringguru.cn/design-patterns/chain-of-responsibility/python/example 定义抽象处理者接口及具体处理者类,通过 set_next 方法构建处理链。 ```python from __future__ import annotations from abc import ABC, abstractmethod from typing import Any, Optional class Handler(ABC): """ The Handler interface declares a method for building the chain of handlers. It also declares a method for executing a request. """ @abstractmethod def set_next(self, handler: Handler) -> Handler: pass @abstractmethod def handle(self, request) -> Optional[str]: pass class AbstractHandler(Handler): """ The default chaining behavior can be implemented inside a base handler class. """ _next_handler: Handler = None def set_next(self, handler: Handler) -> Handler: self._next_handler = handler # Returning a handler from here will let us link handlers in a # convenient way like this: # monkey.set_next(squirrel).set_next(dog) return handler @abstractmethod def handle(self, request: Any) -> str: if self._next_handler: return self._next_handler.handle(request) return None """ All Concrete Handlers either handle a request or pass it to the next handler in the chain. """ class MonkeyHandler(AbstractHandler): def handle(self, request: Any) -> str: if request == "Banana": return f"Monkey: I'll eat the {request}" else: return super().handle(request) class SquirrelHandler(AbstractHandler): def handle(self, request: Any) -> str: if request == "Nut": return f"Squirrel: I'll eat the {request}" else: return super().handle(request) class DogHandler(AbstractHandler): def handle(self, request: Any) -> str: if request == "MeatBall": return f"Dog: I'll eat the {request}" else: return super().handle(request) def client_code(handler: Handler) -> None: """ The client code is usually suited to work with a single handler. In most cases, it is not even aware that the handler is part of a chain. """ for food in ["Nut", "Banana", "Cup of coffee"]: print(f"\nClient: Who wants a {food}?") result = handler.handle(food) if result: print(f" {result}", end="") else: print(f" {food} was left untouched.", end="") if __name__ == "__main__": monkey = MonkeyHandler() squirrel = SquirrelHandler() dog = DogHandler() monkey.set_next(squirrel).set_next(dog) # The client should be able to send a request to any handler, not just the # first one in the chain. print("Chain: Monkey > Squirrel > Dog") client_code(monkey) print("\n") print("Subchain: Squirrel > Dog") client_code(squirrel) ``` -------------------------------- ### Execute Bridge Pattern Demo Source: https://refactoringguru.cn/design-patterns/bridge/java/example The Demo class initializes devices and remotes to demonstrate the interaction between abstractions and implementations. ```java package refactoring_guru.bridge.example; import refactoring_guru.bridge.example.devices.Device; import refactoring_guru.bridge.example.devices.Radio; import refactoring_guru.bridge.example.devices.Tv; import refactoring_guru.bridge.example.remotes.AdvancedRemote; import refactoring_guru.bridge.example.remotes.BasicRemote; public class Demo { public static void main(String[] args) { testDevice(new Tv()); testDevice(new Radio()); } public static void testDevice(Device device) { System.out.println("Tests with basic remote."); BasicRemote basicRemote = new BasicRemote(device); basicRemote.power(); device.printStatus(); System.out.println("Tests with advanced remote."); AdvancedRemote advancedRemote = new AdvancedRemote(device); advancedRemote.power(); advancedRemote.mute(); device.printStatus(); } } ```