Overview
In software systems, we sometimes use inheritance to extend the functions of objects. However, due to the static characteristics introduced by inheritance as types, this expansion method lacks flexibility; as the number of child classes increases (the number of extended functions), the combination of various child classes (the combination of extended functions) will lead to the expansion of more child classes. How can we enable "Object Function Extension" to be dynamically implemented as needed? At the same time, avoid the subclass expansion problem caused by "more extended functions? So that any "function scaling changes" will cause the lowest impact? This is the Decorator mode described in this article.
In one scenario, we need to dynamically add new roles to an object. This role does not modify the original behaviors, but adds new functions based on the original behaviors, it is like a decoration worker applying colorful paint to a new wall.
Intention
Dynamically add some additional responsibilities to an object. The Decorator mode is more flexible than the subclass generation function. [GOF design patterns]
<Design Pattern> structure chart
Figure 1 Decorator mode structure
In the decoration mode, the roles are:
- Abstract Component role: provides an abstract interface to standardize the objects that are prepared to receive additional responsibilities.
- Concrete Component role: defines a class that will receive additional responsibilities.
- Decorator: holds an instance of a Component object and defines an interface consistent with the abstract Component Interface.
- Concrete Decorator: attaches "additional responsibilities to the component object.
Examples in life
The decoration mode dynamically adds additional responsibilities to an object. A painting can be mounted to a wall, whether it is a picture or a frame, but it is usually a frame that is actually mounted to a wall. Before hanging on the wall, the painting can be covered with glass and mounted into the frame. At this time, the painting, glass and frame form an object.
Figure 2 decorative pattern object graph with a framed image as an Example
Example
In supermarkets, there are promotions for common festivals and different festivals have different promotions. We use the decoration mode to write an example of supermarket festival discounts. The example is shown below:
Code Design
Create SuperMarket. cs First:
public abstract class SuperMarket { private int _CategoryNumber; public int CategoryNumber { get { return _CategoryNumber; } set { _CategoryNumber = value; } } private string _Name; public string Name { get { return _Name; } set { _Name = value; } } private double _Discount; public double Discount { get { return _Discount; } set { _Discount = value; } } private string _Festival; public string Festival { get { return _Festival; } set { _Festival = value; } } public abstract string ShowInfo(); }
Create Decorator. cs again:
public abstract class Decorator : SuperMarket { protected SuperMarket superMarker; public Decorator(SuperMarket superMarker) { this.superMarker = superMarker; } public override string ShowInfo() { return superMarker.ShowInfo(); } }
Create WalMart. cs again:
Public class WalMart: SuperMarket {public WalMart () {this. categoryNumber = 1000; this. discount = 0.95; this. name = "Walmart"; this. festival = "normal";} public override string ShowInfo () {StringBuilder strBuilder = new StringBuilder (); strBuilder. appendFormat ("during the {0} supermarket, {1} holiday period, the discount for {2} is {3} type
.", this.Name,this.Festival, this.Discount, this.CategoryNumber); return strBuilder.ToString(); } }
Create MidAutumnFestival. cs:
Public class MidAutumnFestival: Decorator {public MidAutumnFestival (SuperMarket superMarket): base (superMarket) {} public void Preferential () {superMarker. discount = 0.95; superMarker. categoryNumber = 1500; superMarker. festival = "Mid-Autumn Festival";} public string MoonCake () {return "off all moon cakes During the Period ";}}
Create SpringFestival. cs again:
Public class SpringFestival: Decorator {public SpringFestival (SuperMarket supermarket): base (supermarket) {} public void Preferential () {superMarker. discount = 0.9; superMarker. categoryNumber = 2100; superMarker. festival = "Spring Festival";} public string GiftPreferential () {return "offers a 100 off discount for gift products. ";}}
Finally, call:
public partial class Run : Form { public Run() { InitializeComponent(); } private void btnRun_Click(object sender, EventArgs e) { //------------------------------------- SuperMarket superMarket = new WalMart(); rtbResult.AppendText(superMarket.ShowInfo()+""); SpringFestival springFestival = new SpringFestival(superMarket); springFestival.Preferential(); rtbResult.AppendText(springFestival.ShowInfo()); rtbResult.AppendText(springFestival.GiftPreferential()+""); MidAutumnFestival midAutumnFestival = new MidAutumnFestival(superMarket); midAutumnFestival.Preferential(); rtbResult.AppendText(midAutumnFestival.ShowInfo()); rtbResult.AppendText(midAutumnFestival.MoonCake() + ""); } }
The result is as follows: