装饰器模式介绍
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
装饰器模式
using UnityEngine;
using System.Collections;
namespace DecoratorStructure
{
public class DecoratorStructure : MonoBehaviour
{
void Start ( )
{
// Create ConcreteComponent and two Decorators
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA();
ConcreteDecoratorB d2 = new ConcreteDecoratorB();
// Link decorators
d1.SetComponent(c);
d2.SetComponent(d1);
d2.Operation();
}
}
/// <summary>
/// The 'Component' abstract class
/// </summary>
abstract class Component
{
public abstract void Operation();
}
/// <summary>
/// The 'ConcreteComponent' class
/// </summary>
class ConcreteComponent : Component
{
public override void Operation()
{
Debug.Log("ConcreteComponent.Operation()");
}
}
/// <summary>
/// The 'Decorator' abstract class
/// </summary>
abstract class Decorator : Component
{
protected Component component;
public void SetComponent(Component component)
{
this.component = component;
}
public override void Operation()
{
if (component != null)
{
component.Operation();
}
}
}
/// <summary>
/// The 'ConcreteDecoratorA' class
/// </summary>
class ConcreteDecoratorA : Decorator
{
public override void Operation()
{
base.Operation();
Debug.Log("ConcreteDecoratorA.Operation()");
}
}
/// <summary>
/// The 'ConcreteDecoratorB' class
/// </summary>
class ConcreteDecoratorB : Decorator
{
public override void Operation()
{
base.Operation();
AddedBehavior();
Debug.Log("ConcreteDecoratorB.Operation()");
}
void AddedBehavior()
{
}
}
}
装饰器模式案例1
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//这段代码演示了Decorator模式,其中包含“可借用”功能
//添加到现有的图书馆项目(书籍和视频)。
namespace DecoratorPatternExample1
{
public class DecoratorPatternExample1 : MonoBehaviour
{
void Start()
{
// Create book
Book book = new Book("Worley", "Inside ASP.NET", 10);
book.Display();
// Create video
Video video = new Video("Spielberg", "Jaws", 23, 92);
video.Display();
// Make video borrowable, then borrow and display
Debug.Log("\nMaking video borrowable:");
Borrowable borrowvideo = new Borrowable(video);
borrowvideo.BorrowItem("Customer #1");
borrowvideo.BorrowItem("Customer #2");
borrowvideo.Display();
}
}
/// <summary>
/// The 'Component' abstract class
/// </summary>
abstract class LibraryItem
{
private int _numCopies;
// Property
public int NumCopies
{
get { return _numCopies; }
set { _numCopies = value; }
}
public abstract void Display();
}
/// <summary>
/// The 'ConcreteComponent' class
/// </summary>
class Book : LibraryItem
{
private string _author;
private string _title;
// Constructor
public Book(string author, string title, int numCopies)
{
this._author = author;
this._title = title;
this.NumCopies = numCopies;
}
public override void Display()
{
Debug.Log("\nBook ------ ");
Debug.Log(" Author: "+ _author);
Debug.Log(" Title: "+ _title);
Debug.Log(" # Copies: "+ NumCopies);
}
}
/// <summary>
/// The 'ConcreteComponent' class
/// </summary>
class Video : LibraryItem
{
private string _director;
private string _title;
private int _playTime;
// Constructor
public Video(string director, string title,
int numCopies, int playTime)
{
this._director = director;
this._title = title;
this.NumCopies = numCopies;
this._playTime = playTime;
}
public override void Display()
{
Debug.Log("\nVideo ----- ");
Debug.Log(" Director: "+ _director);
Debug.Log(" Title: "+ _title);
Debug.Log(" # Copies: "+ NumCopies);
Debug.Log(" Playtime: "+ _playTime+ "\n");
}
}
/// <summary>
/// The 'Decorator' abstract class
/// </summary>
abstract class Decorator : LibraryItem
{
protected LibraryItem libraryItem;
// Constructor
public Decorator(LibraryItem libraryItem)
{
this.libraryItem = libraryItem;
}
public override void Display()
{
libraryItem.Display();
}
}
/// <summary>
/// The 'ConcreteDecorator' class
/// </summary>
class Borrowable : Decorator
{
protected List<string> borrowers = new List<string>();
// Constructor
public Borrowable(LibraryItem libraryItem)
: base(libraryItem)
{
}
public void BorrowItem(string name)
{
borrowers.Add(name);
libraryItem.NumCopies--;
}
public void ReturnItem(string name)
{
borrowers.Remove(name);
libraryItem.NumCopies++;
}
public override void Display()
{
base.Display();
foreach (string borrower in borrowers)
{
Debug.Log(" borrower: " + borrower);
}
}
}
}
装饰器模式案例2
using UnityEngine;
using System.Collections;
namespace DecoratorPatternExample2
{
public class DecoratorPatternExample2 : MonoBehaviour
{
void Start()
{
// Make Pizzas:
IPizza basicPizza = new TomatoSauce(new Mozzarella(new PlainPizza()));
Debug.Log("Ingredients of Pizza: " + basicPizza.GetDescription());
Debug.Log("Total Cost: " + basicPizza.GetCost());
}
}
public interface IPizza
{
string GetDescription();
double GetCost();
}
public class PlainPizza : IPizza
{
public string GetDescription()
{
return "Thin Dough";
}
public double GetCost()
{
return 4.00;
}
}
public abstract class ToppingDecorator : IPizza
{
protected IPizza tempPizza;
public ToppingDecorator(IPizza newPizza)
{
this.tempPizza = newPizza;
}
public virtual string GetDescription()
{
return tempPizza.GetDescription();
}
public virtual double GetCost()
{
return tempPizza.GetCost();
}
}
public class Mozzarella : ToppingDecorator
{
public Mozzarella(IPizza newPizza) : base(newPizza)
{
Debug.Log("Adding Dough");
Debug.Log("Adding Morarella");
}
public override string GetDescription()
{
return tempPizza.GetDescription() + ", Mozzarella";
}
public override double GetCost()
{
return tempPizza.GetCost() + 0.50;
}
}
public class TomatoSauce : ToppingDecorator
{
public TomatoSauce(IPizza newPizza) : base(newPizza)
{
Debug.Log("Adding Sauce");
}
public override string GetDescription()
{
return tempPizza.GetDescription() + ", Tomato Sauce";
}
public override double GetCost()
{
return tempPizza.GetCost() + 0.35;
}
}
namespace BadStyleExample
{
public abstract class Pizza
{
public abstract void SetDescription(string newDescription);
public abstract string GetDescription();
public abstract double GetCost();
//public abstract bool HasFontina();
}
// this way would force to create an infinite amount of subclasses for each type of pizza
// and if cost if calculated off of individual topings you would have to change cost for all pizzas
// if cost for one topping chages
public class ThreeCheesePizza : Pizza
{
public override void SetDescription(string newDescription)
{
}
public override string GetDescription()
{
return "Mozarella, Fontina, Parmesan, Cheese Pizza";
}
public override double GetCost()
{
return 10.00;
}
}
}
}