Autumn SALE
享元

C# 享元模式讲解和代码示例

享元是一种结构型设计模式 它允许你在消耗少量内存的情况下支持大量对象

模式通过共享多个对象的部分状态来实现上述功能 换句话来说 享元会将不同对象的相同数据进行缓存以节省内存

复杂度

流行度

使用示例 享元模式只有一个目的 将内存消耗最小化 如果你的程序没有遇到内存容量不足的问题 则可以暂时忽略该模式

识别方法 享元可以通过构建方法来识别 它会返回缓存对象而不是创建新的对象

概念示例

本例说明了享元设计模式的结构并重点回答了下面的问题

  • 它由哪些类组成
  • 这些类扮演了哪些角色
  • 模式中的各个元素会以何种方式相互关联

Program.cs: 概念示例

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<Tuple<Flyweight, string>> flyweights = new List<Tuple<Flyweight, string>>(); public FlyweightFactory(params Car[] args) { foreach (var elem in args) { flyweights.Add(new Tuple<Flyweight, string>(new Flyweight(elem), this.getKey(elem))); } } // Returns a Flyweight's string hash for a given state. public string getKey(Car key) { List<string> elements = new List<string>(); 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<Flyweight, string>(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" }); addCarToPoliceDatabase(factory, new Car { Number = "CL234IR", Owner = "James Doe", Company = "BMW", Model = "X1", Color = "red" }); factory.listFlyweights(); } public static void addCarToPoliceDatabase(FlyweightFactory factory, Car car) { Console.WriteLine("\nClient: Adding a car to database."); var flyweight = factory.GetFlyweight(new Car { Color = car.Color, Model = car.Model, Company = car.Company }); // The client code either stores or calculates extrinsic state and // passes it to the flyweight's methods. flyweight.Operation(car); } } } 

Output.txt: 执行结果

FlyweightFactory: I have 5 flyweights: Camaro2018_Chevrolet_pink black_C300_Mercedes Benz C500_Mercedes Benz_red BMW_M5_red BMW_white_X6 Client: Adding a car to database. FlyweightFactory: Reusing existing flyweight. Flyweight: Displaying shared {"Owner":null,"Number":null,"Company":"BMW","Model":"M5","Color":"red"} and unique {"Owner":"James Doe","Number":"CL234IR","Company":"BMW","Model":"M5","Color":"red"} state. Client: Adding a car to database. FlyweightFactory: Can't find a flyweight, creating new one. Flyweight: Displaying shared {"Owner":null,"Number":null,"Company":"BMW","Model":"X1","Color":"red"} and unique {"Owner":"James Doe","Number":"CL234IR","Company":"BMW","Model":"X1","Color":"red"} state. FlyweightFactory: I have 6 flyweights: Camaro2018_Chevrolet_pink black_C300_Mercedes Benz C500_Mercedes Benz_red BMW_M5_red BMW_white_X6 BMW_red_X1 

享元在其他编程语言中的实现

C++ 享元模式讲解和代码示例 Go 享元模式讲解和代码示例 Java 享元模式讲解和代码示例 PHP 享元模式讲解和代码示例 Python 享元模式讲解和代码示例 Ruby 享元模式讲解和代码示例 Rust 享元模式讲解和代码示例 Swift 享元模式讲解和代码示例 TypeScript 享元模式讲解和代码示例