装饰者模式么,在生活中我们是经常接触的。比如像我们这么快节奏的生活,好多都是早上去买煎饼。一般我们会这么说:“来一个粗粮煎饼,加两个鸡蛋,加一根肠”
或者:“来个山东煎饼,只加土豆丝”等等。“煎饼” 就是这个么个有弹性的对象,面饼是不变的,其它的像鸡蛋,肠什么的者在装饰面饼。这个也是我们编程时的一个设计原则
对扩展开放,对修改关闭。(在最后我会给出C# 和C++ 两种代码示例)
装饰者模式和“煎饼”差不多,它可以动态地将责任("鸡蛋“、“肠”...)附加到对象(”煎饼“)上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
我们看一下装饰者模式的类图:
看这个类图我们可以总结一下装饰者模式的特点:
1.被装饰对象和装饰品有相同的接口。这样装饰品和被装饰对象就可以相互交互。
2.装饰品对象包含一个被装饰对象的引用。
让我们做一个煎饼吧:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DecoratorDemo { [Flags] public enum BcType { None = 0, // 0 SdCakeType, // 山东煎饼 EggType, // 蛋 SausageType // 肠 } public interface IBatterCake { List<BcType> Type(); double Coast(); } public class NoneBatterCake : IBatterCake { public List<BcType> Type() { return new List<BcType> {BcType.None}; } public double Coast() { return 0; } } /// <summary> /// 山东煎饼 /// </summary> public class SdBatterCake : IBatterCake { public List<BcType> Type() { return new List<BcType> {BcType.SdCakeType}; } public double Coast() { return 3.5; } } /// <summary> /// 鸡蛋 /// </summary> public class Egg : IBatterCake { private readonly IBatterCake _batterCake = new NoneBatterCake(); public Egg(IBatterCake mMoney) { _batterCake = mMoney; } public List<BcType> Type() { List<BcType> types = _batterCake.Type(); types.AddRange(new List<BcType>() { BcType.EggType }); return types; } public double Coast() { return 1 + _batterCake.Coast(); } } /// <summary> /// 肠 /// </summary> public class Sausage : IBatterCake { private readonly IBatterCake _batterCake = new NoneBatterCake(); public Sausage(IBatterCake mMoney) { _batterCake = mMoney; } public List<BcType> Type() { List<BcType> types = _batterCake.Type(); types.AddRange(new List<BcType>() { BcType.SausageType }); return types; } public double Coast() { return 2 + _batterCake.Coast(); } } /// <summary> /// 计算花费 /// </summary> public class CalculateMoney : IBatterCake { private readonly IBatterCake _batterCake = new NoneBatterCake(); public CalculateMoney(IBatterCake mMoney) { _batterCake = mMoney; } public List<BcType> Type() { return new List<BcType> {BcType.None}; } public string Description() { List<BcType> types = _batterCake.Type(); int eggs = 0, sausage = 0,battercakies = 0; for (int index = 0, count = types.Count(); index < count; index++) { if (types[index] == BcType.SdCakeType) battercakies++; if (types[index] == BcType.EggType) eggs++; if (types[index] == BcType.SausageType) sausage++; } StringBuilder description = new StringBuilder(); if (battercakies > 0) description.Append("煎饼").Append(battercakies).Append("个").Append("\n"); if (eggs > 0) description.Append("鸡蛋").Append(eggs).Append("个").Append("\n"); if (sausage > 0) description.Append("烤肠").Append(sausage).Append("个").Append("\n"); return description.ToString(); } public double Coast() { return _batterCake.Coast(); } } public class Program { private static void Main(string[] args) { // 一个山东煎饼 IBatterCake sdBatterCake = new SdBatterCake(); // 一个鸡蛋 IBatterCake egg1 = new Egg(sdBatterCake); // 再来个鸡蛋 IBatterCake egg2 = new Egg(egg1); // 再来个肠 IBatterCake sausage = new Sausage(egg2); CalculateMoney calculateMoney = new CalculateMoney(sausage); Console.WriteLine(calculateMoney.Description()); Console.WriteLine("共花费 : {0}", calculateMoney.Coast()); Console.ReadLine(); } } }
看一下结果:
c++代码:
#include <iostream> #include <string> #include <list> using namespace std; enum class BcType { None = 0, // 0 SdCakeType, // 山东煎饼 EggType, // 蛋 SausageType // 肠 }; class IBatterCake { public: virtual ~IBatterCake() {} virtual list<BcType> type() const = 0; virtual double coast() const = 0; }; class NoneBatterCake : public IBatterCake { public: NoneBatterCake() {} virtual ~NoneBatterCake() { } virtual list<BcType> type() const override { return list<BcType>{ BcType::None }; } virtual double coast() const override { return 0; } }; /// <summary> /// 山东煎饼 /// </summary> class SdBatterCake : public IBatterCake { public: SdBatterCake() {} virtual ~SdBatterCake() { } virtual list<BcType> type() const override { return list<BcType>{ BcType::SdCakeType }; } virtual double coast() const override { return 3.5; } }; /// <summary> /// 鸡蛋 /// </summary> class Egg : public IBatterCake { public: Egg() {} Egg(IBatterCake *batter) { if (m_batter) delete m_batter; m_batter = batter; } ~Egg() { delete m_batter; } virtual list<BcType> type() const override { list<BcType> ls = m_batter->type(); ls.push_back(BcType::EggType); return ls; } virtual double coast() const override { return 3.5 + m_batter->coast(); } private: IBatterCake *m_batter = new NoneBatterCake(); }; /// <summary> /// 肠 /// </summary> class Sausage: public IBatterCake { public: Sausage() {} Sausage(IBatterCake *batter) { if (m_batter) delete m_batter; m_batter = batter; } ~Sausage() { delete m_batter; } virtual list<BcType> type() const override { list<BcType> ls = m_batter->type(); ls.push_back(BcType::SausageType); return ls; } virtual double coast() const override { return 2 + m_batter->coast(); } private: IBatterCake *m_batter = new NoneBatterCake(); }; /// <summary> /// 计算花费 /// </summary> class CalculateMoney : public IBatterCake { public: CalculateMoney(IBatterCake *batter) { if (m_batter) delete m_batter; m_batter = batter; } ~CalculateMoney() { delete m_batter; } virtual list<BcType> type() const override { return list<BcType>{ BcType::None }; } string description() { list<BcType> types = m_batter->type(); int eggs = 0, sausage = 0, battercakies = 0; for (const BcType &type : types) { if (type == BcType::SdCakeType) battercakies++; if (type == BcType::EggType) eggs++; if (type == BcType::SausageType) sausage++; } string description; if (battercakies > 0) description.append("煎饼").append(std::to_string(battercakies)).append("个\n"); if (eggs > 0) description.append("加").append(std::to_string(eggs)).append("个鸡蛋\n"); if (sausage > 0) description.append("加").append(std::to_string(sausage)).append("个烤肠\n"); return description; } virtual double coast() const override { return m_batter->coast(); } private: IBatterCake *m_batter = new NoneBatterCake(); }; int main() { IBatterCake *sdBatterCake = new SdBatterCake(); IBatterCake *egg1 = new Egg(sdBatterCake); IBatterCake *egg2 = new Egg(egg1); IBatterCake *sausage = new Sausage(egg2); CalculateMoney *calculateMoney = new CalculateMoney(sausage); cout << calculateMoney->description(); delete calculateMoney; cin.get(); return 0; }
View Code
结果是一样的
以下情况使用Decorator模式
1. 需要扩展一个类的功能,或给一个类添加附加职责。
2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
时间: 2024-09-21 08:46:09