惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
GbyAI
GbyAI
C
CERT Recently Published Vulnerability Notes
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Hacker News
The Hacker News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
P
Proofpoint News Feed
C
Cyber Attacks, Cyber Crime and Cyber Security
S
Securelist
Security Latest
Security Latest
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Simon Willison's Weblog
Simon Willison's Weblog
Latest news
Latest news
T
Tor Project blog
T
Threat Research - Cisco Blogs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Spread Privacy
Spread Privacy
K
Kaspersky official blog
T
The Exploit Database - CXSecurity.com
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
V2EX - 技术
V2EX - 技术
L
Lohrmann on Cybersecurity
Google Online Security Blog
Google Online Security Blog
Cyberwarzone
Cyberwarzone
Help Net Security
Help Net Security
The Last Watchdog
The Last Watchdog
C
Cybersecurity and Infrastructure Security Agency CISA
Attack and Defense Labs
Attack and Defense Labs
大猫的无限游戏
大猫的无限游戏
Schneier on Security
Schneier on Security
H
Heimdal Security Blog
O
OpenAI News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
AI
AI
H
Hacker News: Front Page
博客园_首页
博客园 - 【当耐特】
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
量子位
Vercel News
Vercel News
C
Cisco Blogs
L
LINUX DO - 热门话题
Y
Y Combinator Blog
T
Threatpost
爱范儿
爱范儿
P
Privacy & Cybersecurity Law Blog

博客园 - BigRain

小学生学习汉字,汉字抓取 c# regex regextools cache 访问频率的思考 python 百度cpc点击 20130118SQL记录 PPT辅助工具 检查外链的方法 webService启用cookie的另一种方法 百度调价HttpWebRequest 第一个android程序闪亮登场 SQL 的一些批量插入和修改 职责链模式的运用 State Pattern 程序人生 SerialPort实现modem的来电显示 利用枚举进行状态的设计 singleton模式 在软件开发中的运用 我对当前项目的一些看法 闲话闲说——关于异常
装饰者模式
BigRain · 2011-08-09 · via 博客园 - BigRain

对于一个初学设计模式的人来说,装饰者模式是很头疼的,因为我们一般很少会在项目中使用到这种模式(或者是个人的喜好吧)。装饰者模式是为了更为灵活的扩展对象的方法。

一般情况下,我们要扩展一个对象的方法,我们会用到继承,或者将对象内聚进去。但是,继承的扩展相对来说是静止的扩展,就是说一个方法扩展后,如果想继续新增功能的话,必须再次继承,再次扩展方法。这样的扩展就很容易引起子类的膨胀。

我想引入一个例子,就是tlw旁边的莆田卤面(听说又涨价啦),莆田卤面的做法比较灵活,可以加入多种佐料。比如 花蛤、虾、海蛎、蛏、蘑菇、猪肉。卤面中可以加入一种或者几种佐料,很显然,如果要为卤面加佐料的话,根据单一职责,需要派生出21种来子类来(6+5+4+3+2+1)。这样一来,就会出现子类膨胀,难以维护,而且对于边际扩展来说,所需要派生出来的子类就更多了(如果有10种配料的话,需要的子类是10+9+8+...+2+1)。

而装饰者模式就是为了解决这个问题的。装饰者模式的意图就是:动态地给一个对象添加一些额外的职责。

    /// <summary>
    /// 面条
    /// </summary>
    public class Noodles
    {
    }

    /// <summary>
    /// 佐料
    /// </summary>
    public abstract class Condiments
    {
        /// <summary>
        /// 往苗条里面加佐料
        /// </summary>
        /// <param name="noodles"></param>
        public abstract void CondimentsToNoodles(Noodles noodles);
    }
    //一般的调味品
    public class GeneralCondiments : Condiments
    {
        public override void CondimentsToNoodles(Noodles noodles)
        {
            //加入一般的调味品
        }
    }

    /// <summary>
    /// 配料装饰者
    /// </summary>
    public class CondimentsDecorator : Condiments
    {
        private Condiments _Condiments;
        public CondimentsDecorator(Condiments condiments)
        {
            this._Condiments = condiments;
        }

        /// <summary>
        /// 将佐料加入面条
        /// </summary>
        /// <param name="noodles"></param>
        public override void CondimentsToNoodles(Noodles noodles)
        {
            this._Condiments.CondimentsToNoodles(noodles);
        }
    }

接着扩展配料:

    /// <summary>
    /// 花蛤
    /// </summary>
    public class Clam : CondimentsDecorator
    {
        public Clam(Condiments condiments)
            : base(condiments)
        {
        }
        public override void CondimentsToNoodles(Noodles noodles)
        {
            base.CondimentsToNoodles(noodles); AddClamToNoodles(noodles);
   }
        private void AddClamToNoodles(Noodles noodles)
        {
            //往面条里面加入花蛤
        }
    }

    /// <summary>
    /// 虾
    /// </summary>
    public class Shrimp : CondimentsDecorator
    {
        public Shrimp(Condiments condiments)
            : base(condiments)
        { 
        }
        public override void CondimentsToNoodles(Noodles noodles)
        {
            base.CondimentsToNoodles(noodles); AddClamToNoodles(noodles);
} private void AddShrimp2Noodles(Noodles noodles) { //往面条里面加虾 } } /// <summary> /// 蘑菇 /// </summary> public class Mushrooms : CondimentsDecorator { public Mushrooms(Condiments condiments) : base(condiments) { } public override void CondimentsToNoodles(Noodles noodles) { base.CondimentsToNoodles(noodles); AddMushrooms2Noodles(noodles); } private void AddMushrooms2Noodles(Noodles noodles) { //往面条里面加蘑菇 } } /// <summary> /// 猪肉 /// </summary> public class Pork : CondimentsDecorator { public Pork(Condiments condiments) : base(condiments) { } public override void CondimentsToNoodles(Noodles noodles) { base.CondimentsToNoodles(noodles); AddPork2Noodles(noodles); } private void AddPork2Noodles(Noodles noodles) { //往面条里面加猪肉 } }

最后调用:

            //莆田卤面
            Noodles putianNoodles = new Noodles();

            GeneralCondiments general = new GeneralCondiments();
            Clam clam = new Clam(general);
            Shrimp shrimp = new Shrimp(clam);
            Mushrooms mushrooms = new Mushrooms(shrimp);
            Pork pork = new Pork(mushrooms);

            pork.CondimentsToNoodles(putianNoodles);

上面的调用加入了所有的佐料,我们可以根据需要,灵活的添加不同组合的佐料。

装饰者模式的奥妙就是将装饰者和被装饰者使用的是一种类型;并且将被装饰者集聚到装饰者的类中,这种设计方式,使得扩展变得容易,并且灵活。

可以这么简单的理解,遇到一些子类需要选择组合的时候,使用装饰者模式将是子类的扩展变得很灵活,不会出现子类泛滥的情况。

我在学习设计模式的过程中,觉得最难理解的就是装饰者了,因为这种模式在我所遇到的项目里不常用到。