« Flyweight pattern » : différence entre les versions
De Banane Atomic
Aller à la navigationAller à la recherche
(Page créée avec « Category:CSharp Category:Design Patterns = Description = * Use sharing to support large numbers of fine-grained objects efficiently ») |
|||
(7 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
[[Category:CSharp]] | [[Category:CSharp]] | ||
[[Category:Design Patterns]] | [[Category:Design Patterns]] | ||
= | = Definition = | ||
Use sharing to support large numbers of fine-grained objects efficiently. | |||
* Split heavy objects into what can be shared (flyweight / template / intrinsic data) and what to be configured (context / extrinsic data) | |||
* The heavy object can be generated on the fly from the flyweight object and the context | |||
* Reduce the memory cost of working with large numbers of very small objects | |||
== Flyweight vs Singleton == | |||
* flyweight pattern is acting like a common template that can be configured as per the need | |||
* singleton pattern allows to reuse an existing object | |||
== Multithreading == | |||
Same problem and remedy as the Singleton pattern. | |||
= Exemple = | |||
<filebox fn='User.cs'> | |||
public class User | |||
{ | |||
public string Name { get; set; } | |||
public override string ToString() => $"Simple user: {Name}"; | |||
} | |||
</filebox> | |||
<filebox fn='Administrator.cs'> | |||
public class Administrator : User | |||
{ | |||
public override string ToString() => $"Admin user: {Name}"; | |||
} | |||
</filebox> | |||
<filebox fn='UserFactory.cs'> | |||
public class UserFactory | |||
{ | |||
IDictionary<UserType, User> userTemplatesByUserType = new Dictionary<UserType, User>(); | |||
public User GetUserFromFactory(UserType userType) | |||
{ | |||
User userTemplate = null; | |||
if (userTemplatesByUserType.ContainsKey(userType)) | |||
{ | |||
userTemplate = userTemplatesByUserType[userType]; | |||
} | |||
else | |||
{ | |||
switch (userType) | |||
{ | |||
case UserType.User: | |||
userTemplate = new User(); | |||
userTemplatesByUserType.Add(UserType.User, userTemplate); | |||
break; | |||
case UserType.Administrator: | |||
userTemplate = new Administrator(); | |||
userTemplatesByUserType.Add(UserType.Administrator, userTemplate); | |||
break; | |||
case UserType.Guest: | |||
userTemplate = new Guest(); | |||
userTemplatesByUserType.Add(UserType.Guest, userTemplate); | |||
break; | |||
default: | |||
throw new Exception($"Unknown user type {userType}."); | |||
} | |||
} | |||
return userTemplate; | |||
} | |||
} | |||
</filebox> | |||
<kode lang='cs'> | |||
var userFactory = new UserFactory(); | |||
var user = userFactory.GetUserFromFactory(UserType.User); | |||
user.Name = "Nicolas"; | |||
Console.WriteLine(user); | |||
for (var i = 0; i < 10; i++) | |||
{ | |||
// call only once the Administrator ctor then reuse the instance | |||
user = userFactory.GetUserFromFactory(UserType.Administrator); | |||
user.Name = $"Admin{i}"; | |||
Console.WriteLine(user); | |||
} | |||
</kode> |
Dernière version du 7 juin 2020 à 15:33
Definition
Use sharing to support large numbers of fine-grained objects efficiently.
- Split heavy objects into what can be shared (flyweight / template / intrinsic data) and what to be configured (context / extrinsic data)
- The heavy object can be generated on the fly from the flyweight object and the context
- Reduce the memory cost of working with large numbers of very small objects
Flyweight vs Singleton
- flyweight pattern is acting like a common template that can be configured as per the need
- singleton pattern allows to reuse an existing object
Multithreading
Same problem and remedy as the Singleton pattern.
Exemple
User.cs |
public class User { public string Name { get; set; } public override string ToString() => $"Simple user: {Name}"; } |
Administrator.cs |
public class Administrator : User { public override string ToString() => $"Admin user: {Name}"; } |
UserFactory.cs |
public class UserFactory { IDictionary<UserType, User> userTemplatesByUserType = new Dictionary<UserType, User>(); public User GetUserFromFactory(UserType userType) { User userTemplate = null; if (userTemplatesByUserType.ContainsKey(userType)) { userTemplate = userTemplatesByUserType[userType]; } else { switch (userType) { case UserType.User: userTemplate = new User(); userTemplatesByUserType.Add(UserType.User, userTemplate); break; case UserType.Administrator: userTemplate = new Administrator(); userTemplatesByUserType.Add(UserType.Administrator, userTemplate); break; case UserType.Guest: userTemplate = new Guest(); userTemplatesByUserType.Add(UserType.Guest, userTemplate); break; default: throw new Exception($"Unknown user type {userType}."); } } return userTemplate; } } |
var userFactory = new UserFactory(); var user = userFactory.GetUserFromFactory(UserType.User); user.Name = "Nicolas"; Console.WriteLine(user); for (var i = 0; i < 10; i++) { // call only once the Administrator ctor then reuse the instance user = userFactory.GetUserFromFactory(UserType.Administrator); user.Name = $"Admin{i}"; Console.WriteLine(user); } |