odi*_*seh 163 design-patterns decorator
我正在研究GOF中记载的装饰模式.
请帮我理解装饰模式.有人可以给出一个用例,说明这在现实世界中有用吗?
thi*_*eek 222
装饰器模式实现了向任何对象动态添加职责的单一目标.
考虑一个披萨店的情况.在披萨店,他们将出售少量披萨品种,他们还将在菜单中提供配料.现在设想一种情况,其中如果披萨店必须为披萨和馅料的每种组合提供价格.即使有四种基本的比萨饼和8种不同的浇头,应用程序也会疯狂地保持比萨饼和浇头的所有这些具体组合.
这是装饰图案.
根据装饰器模式,您将实现浇头作为装饰器和比萨将由那些浇头装饰器装饰.实际上,每个顾客都想要满足他的愿望和最终的账单金额将由基础比萨饼和额外的订购配料组成.每个顶级装饰者都会知道它正在装饰的比萨饼和它的价格.Topping对象的GetPrice()方法将返回披萨和顶部的累积价格.
这是上面解释的代码示例.
public abstract class BasePizza
{
protected double myPrice;
public virtual double GetPrice()
{
return this.myPrice;
}
}
public abstract class ToppingsDecorator : BasePizza
{
protected BasePizza pizza;
public ToppingsDecorator(BasePizza pizzaToDecorate)
{
this.pizza = pizzaToDecorate;
}
public override double GetPrice()
{
return (this.pizza.GetPrice() + this.myPrice);
}
}
class Program
{
[STAThread]
static void Main()
{
//Client-code
Margherita pizza = new Margherita();
Console.WriteLine("Plain Margherita: " + pizza.GetPrice().ToString());
ExtraCheeseTopping moreCheese = new ExtraCheeseTopping(pizza);
ExtraCheeseTopping someMoreCheese = new ExtraCheeseTopping(moreCheese);
Console.WriteLine("Plain Margherita with double extra cheese: " + someMoreCheese.GetPrice().ToString());
MushroomTopping moreMushroom = new MushroomTopping(someMoreCheese);
Console.WriteLine("Plain Margherita with double extra cheese with mushroom: " + moreMushroom.GetPrice().ToString());
JalapenoTopping moreJalapeno = new JalapenoTopping(moreMushroom);
Console.WriteLine("Plain Margherita with double extra cheese with mushroom with Jalapeno: " + moreJalapeno.GetPrice().ToString());
Console.ReadLine();
}
}
public class Margherita : BasePizza
{
public Margherita()
{
this.myPrice = 6.99;
}
}
public class Gourmet : BasePizza
{
public Gourmet()
{
this.myPrice = 7.49;
}
}
public class ExtraCheeseTopping : ToppingsDecorator
{
public ExtraCheeseTopping(BasePizza pizzaToDecorate)
: base(pizzaToDecorate)
{
this.myPrice = 0.99;
}
}
public class MushroomTopping : ToppingsDecorator
{
public MushroomTopping(BasePizza pizzaToDecorate)
: base(pizzaToDecorate)
{
this.myPrice = 1.49;
}
}
public class JalapenoTopping : ToppingsDecorator
{
public JalapenoTopping(BasePizza pizzaToDecorate)
: base(pizzaToDecorate)
{
this.myPrice = 1.49;
}
}
Run Code Online (Sandbox Code Playgroud)
Anu*_*rag 32
这是动态向现有对象添加新行为或Decorator模式的简单示例.由于Javascript等动态语言的性质,这种模式成为语言本身的一部分.
// Person object that we will be decorating with logging capability
var person = {
name: "Foo",
city: "Bar"
};
// Function that serves as a decorator and dynamically adds the log method to a given object
function MakeLoggable(object) {
object.log = function(property) {
console.log(this[property]);
}
}
// Person is given the dynamic responsibility here
MakeLoggable(person);
// Using the newly added functionality
person.log('name');
Run Code Online (Sandbox Code Playgroud)
示例 - 场景 - 假设您正在编写加密模块.此加密可以使用DES - 数据加密标准加密明文件.同样,在系统中,您可以将加密设置为AES - 高级加密标准.此外,您可以使用加密组合 - 首先是DES,然后是AES.或者您可以拥有第一个AES,然后是DES.
讨论 - 你将如何迎合这种情况?您无法继续创建此类组合的对象 - 例如 - AES和DES - 总共4种组合.因此,您需要有4个单独的对象随着加密类型的增加,这将变得复杂.
解决方案 - 在运行时继续构建堆栈 - 根据需要组合.这种堆栈方法的另一个优点是您可以轻松解开它.
这是解决方案 - 在C++中.
首先,您需要一个基类 - 堆栈的基本单元.您可以将其视为堆栈的基础.在这个例子中,它是明确的文件.让我们始终遵循多态性.首先制作这个基本单元的接口类.这样,您可以根据需要实现它.此外,在包含此基本单元时,您不需要考虑依赖性.
这是接口类 -
class IclearData
{
public:
virtual std::string getData() = 0;
virtual ~IclearData() = 0;
};
IclearData::~IclearData()
{
std::cout<<"Destructor called of IclearData"<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
现在,实现这个接口类 -
class clearData:public IclearData
{
private:
std::string m_data;
clearData();
void setData(std::string data)
{
m_data = data;
}
public:
std::string getData()
{
return m_data;
}
clearData(std::string data)
{
setData(data);
}
~clearData()
{
std::cout<<"Destructor of clear Data Invoked"<<std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,让我们制作一个装饰器抽象类 - 可以扩展为创建任何类型的风格 - 这里的风格是加密类型.此装饰器抽象类与基类相关.因此,装饰器"是一种"接口类.因此,您需要使用继承.
class encryptionDecorator: public IclearData
{
protected:
IclearData *p_mclearData;
encryptionDecorator()
{
std::cout<<"Encryption Decorator Abstract class called"<<std::endl;
}
public:
std::string getData()
{
return p_mclearData->getData();
}
encryptionDecorator(IclearData *clearData)
{
p_mclearData = clearData;
}
virtual std::string showDecryptedData() = 0;
virtual ~encryptionDecorator() = 0;
};
encryptionDecorator::~encryptionDecorator()
{
std::cout<<"Encryption Decorator Destructor called"<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
现在,让我们制作一个具体的装饰类 - 加密类型 - AES -
const std::string aesEncrypt = "AES Encrypted ";
class aes: public encryptionDecorator
{
private:
std::string m_aesData;
aes();
public:
aes(IclearData *pClearData): m_aesData(aesEncrypt)
{
p_mclearData = pClearData;
m_aesData.append(p_mclearData->getData());
}
std::string getData()
{
return m_aesData;
}
std::string showDecryptedData(void)
{
m_aesData.erase(0,m_aesData.length());
return m_aesData;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,让我们说装饰器类型是DES -
const std :: string desEncrypt ="DES Encrypted";
class des: public encryptionDecorator
{
private:
std::string m_desData;
des();
public:
des(IclearData *pClearData): m_desData(desEncrypt)
{
p_mclearData = pClearData;
m_desData.append(p_mclearData->getData());
}
std::string getData(void)
{
return m_desData;
}
std::string showDecryptedData(void)
{
m_desData.erase(0,desEncrypt.length());
return m_desData;
}
};
Run Code Online (Sandbox Code Playgroud)
让我们创建一个客户端代码来使用这个装饰器类 -
int main()
{
IclearData *pData = new clearData("HELLO_CLEAR_DATA");
std::cout<<pData->getData()<<std::endl;
encryptionDecorator *pAesData = new aes(pData);
std::cout<<pAesData->getData()<<std::endl;
encryptionDecorator *pDesData = new des(pAesData);
std::cout<<pDesData->getData()<<std::endl;
/** unwind the decorator stack ***/
std::cout<<pDesData->showDecryptedData()<<std::endl;
delete pDesData;
delete pAesData;
delete pData;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您将看到以下结果 -
HELLO_CLEAR_DATA
Encryption Decorator Abstract class called
AES Encrypted HELLO_CLEAR_DATA
Encryption Decorator Abstract class called
DES Encrypted AES Encrypted HELLO_CLEAR_DATA
AES Encrypted HELLO_CLEAR_DATA
Encryption Decorator Destructor called
Destructor called of IclearData
Encryption Decorator Destructor called
Destructor called of IclearData
Destructor of clear Data Invoked
Destructor called of IclearData
Run Code Online (Sandbox Code Playgroud)
这是UML图 - 它的类表示.如果您想跳过代码并专注于设计方面.
装饰器模式可帮助您通过与对象的其他类似子类链接来更改或配置对象的功能。
最好的例子是 java.io 包中的 InputStream 和 OutputStream 类
File file=new File("target","test.txt");
FileOutputStream fos=new FileOutputStream(file);
BufferedOutputStream bos=new BufferedOutputStream(fos);
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.write(5);
oos.writeBoolean(true);
oos.writeBytes("decorator pattern was here.");
//... then close the streams of course.
Run Code Online (Sandbox Code Playgroud)