一,装饰者模式(Decorator Pattern):装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。

二,在以上代码中我们是中国人是根本行为,我们给中国人装饰我会说英语,我会说日语和我会说英语我会说日语这三种行为,那按正常的理解来说,这是多态,那我们对People中的Say我们是不是需要有三种实现方法呢?三种还是比较好解决,但是如果我们有N种呢?难道我们要有N个实现类么?这时我们就可以使用装饰者模式。

1》我们抽象People这个类,还有抽象的Say方法方法,这时People就可以有多国人的实现,我们使用一种中国人,假设,这是我们现有的代码的,但根据需求,我们需要给中国人添加我会说英语,我会说日语和我会说英语我会说日语这三种行为,那该怎么办?根据以往想法,一般如下设计:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Demo
{
class Program
{
static void Main(string[] args)
{
People p = new Englist();
p.Say();
People p1 = new Jan();
p1.Say();
People p2 = new JE();
p2.Say();
}
}
public abstract class People
{
public abstract void Say();
}
public class Chinese : People
{
public override void Say()
{
Console.WriteLine("我是中国人");
}
}
public class Englist : Chinese
{
public override void Say()
{
base.Say();
Console.WriteLine("我是会说英语");
}
}
public class Jan : Chinese
{
public override void Say()
{
base.Say();
Console.WriteLine("我是会说日语");
}
}
public class JE : Chinese
{
public override void Say()
{
base.Say();
Console.WriteLine("我是会说英语和日语");
}
}
}

2》然而我们如果还有N种装饰中国人,难道要写N个子类?但是明显是不合理的,这时我们该怎么对chinese扩展呢?我们使用装饰者模式看看,如下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _8.装饰者模式
{
//装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。
class Program
{
static void Main(string[] args)
{
People p = new Chinese(); //没有扩展的实现 Decorator d = new Englist(p); //将会说英语的扩展给中国人
d.Say();
Console.WriteLine("----------------------\n"); Decorator d1 = new Jan(p); //将会说日语的扩展给中国人
d1.Say();
Console.WriteLine("----------------------\n"); Englist e = new Englist(p); //将会说英语和日语的扩展给中国人,这里是装饰者模式的核心,当我们存在这里三种可能的组合时,正常逻辑可能是每一种都实现一次,这样就存在三个实现子类,但是如果可能组合有几十上百种怎么办,这时我们可以使用装饰者模式,在代码中,我们只是实现说英语和说日语的两种可能,但我们可以实现组合得出第三种可能,这样代码就可以减少很多。
Jan j = new Jan(e);
j.Say();
}
} public abstract class People
{
public abstract void Say();
}
public class Chinese : People
{
public override void Say() //根本的行为
{
Console.Write("我是中国人");
}
} public abstract class Decorator : People
{
public People people;
public Decorator(People p)
{
this.people = p;
} public override void Say()
{
people.Say();
}
}
public class Englist : Decorator
{
public Englist(People p)
: base(p)
{
} public override void Say()
{
base.Say(); // 添加新的行为,动态地扩展一个对象的功能
SayEnglish();
} /// <summary>
/// 新的行为方法
/// </summary>
public void SayEnglish()
{
Console.WriteLine("我会说英语");
}
} public class Jan : Decorator
{
public Jan(People p)
: base(p)
{
} public override void Say()
{
base.Say(); // 添加新的行为,动态地扩展一个对象的功能
SayJan();
} /// <summary>
/// 新的行为方法
/// </summary>
public void SayJan()
{
Console.WriteLine("我会说日语");
}
}
}

两个代码对比,我们是不是发现少了一个子类的实现?,这样也减少了代码量。

3》但为什么下面代码可以实现两种组合?我们来理清点思路

Englist e = new Englist(p);
Jan j = new Jan(e);
j.Say();

在上文中,我们的Englist 是继承Decorator而构造变量是People类型,但我们实例Englist 时,我们也传入了一个抽象people接收Chinese创建的中国人实例的变量进来,然后传给Englist ,而此时,人的对象已经传给Englist ,而Englist继承decorator,同时decorator继承people,我们重写Say()并调用的中国人的实现的方法Say()和调用SayEnglist(),这样我们就可以给原本的中国人装饰上说英语这一行为,如下代码:

     public override void Say()
{
base.Say(); // 添加新的行为,动态地扩展一个对象的功能
SayEnglist();
}

4》那我们要同时说英语的日语呢?

根据3》中我么可以知道3中的Say方法代码已经综合了说英文,我们的思路是不是可以说,重写英语的Say(),调用英语的Say()和调用说日语的方法SayJan()就可以了?而不是说实现多一个子类。那为什么下面这句代码可以实现呢?综合了两种说话的行为呢?

Jan j = new Jan(e);

我们来理解下,在上文我们实例的英语已经重写了Say的方法,而此时的Say()是已经包含了说英语的功能,同时Englist继承的父类最根本的就是people,根据继承的原则,我们是不是可以将Englist对象传给people,这里我们在看看Jan内重写Say()方法,并调用说日语的方法,这时不就可以同时给中国人添加两种行为了么

5》相对于同一个具体物件装饰器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _08.装饰者模式
{
/// <summary>
/// 装饰者模式属于结构型模式,装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。
/// 装饰者模式通过创建一个包装对象(wrapper),也就是用装饰来包裹真实的对象。
/// </summary>
class Program
{
static void Main(string[] args)
{
People p = new China();
p = new PeopleDecorator(p);
p = new Chinese(p);
p = new Englist(p);
p.DoSome();
}
}
/// <summary>
/// People充当抽象构件。
/// </summary>
public abstract class People
{
public abstract void DoSome();
}
/// <summary>
/// China充当具体构件
/// </summary>
public class China: People
{
public override void DoSome()
{
Console.WriteLine("我是中国人!!!");
}
}
/// <summary>
/// 抽象装饰(Decorator)
/// </summary>
public class PeopleDecorator : People
{
private People _people = null;
public PeopleDecorator(People people)
{
this._people = people;
}
public override void DoSome()
{
_people.DoSome();
}
}
/// <summary>
/// 具体装饰(Concrete Decorator)
/// </summary>
public class Chinese : PeopleDecorator
{
private People _people = null;
public Chinese(People people) : base(people)
{
this._people = people;
}
public override void DoSome()
{
_people.DoSome();
Console.WriteLine("我说中文");
}
}
/// <summary>
/// 具体装饰(Concrete Decorator)
/// </summary>
public class Englist : Chinese
{
private People _people = null;
public Englist(People people) : base(people)
{
this._people = people;
}
public override void DoSome()
{
_people.DoSome();
Console.WriteLine("我说英语");
}
}
}

C#设计模式:装饰者模式(Decorator Pattern)的更多相关文章

  1. 浅谈设计模式--装饰者模式(Decorator Pattern)

    挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...

  2. 设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 用法

    装饰者模式(Decorator Pattern) Java的IO类 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716 ...

  3. 设计模式 - 装饰者模式(Decorator Pattern) 具体解释

    装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者 ...

  4. C#设计模式——装饰者模式(Decorator Pattern)

    一.例子在软件开发中,我们往往会想要给某一类对象增加不同的功能.比如要给汽车增加ESP.天窗或者定速巡航.如果利用继承来实现,就需要定义无数的类,Car,ESPCar,CCSCar,SunRoofCa ...

  5. 设计模式学习--装饰者模式(Decorator Pattern)

    概念: 装饰者模式(Decorator Pattern): 动态地将功能添加到对象,相比生成子类更灵活,更富有弹性. 解决方案: 装饰者模式的重点是对象的类型,装饰者对象必须有着相同的接口,也也就是有 ...

  6. 大话设计模式--装饰者模式 Decorator -- C++实现实例

    1.装饰者模式 Decorator 动态地给一个对象添加一个额外的职责, 就添加功能来说, 装饰模式比生成子类更为灵活. 每个装饰对象的实现和如何使用这个对象分离,  每个装饰对象只关心自己的功能,不 ...

  7. 23种设计模式之装饰器模式(Decorator Pattern)

    装饰器模式(Decorator Pattern) 允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包 ...

  8. 设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)

    在前两篇博客中详细的介绍了"策略模式"和“观察者模式”,今天我们就通过花瓶与鲜花的例子来类比一下“装饰模式”(Decorator Pattern).在“装饰模式”中很好的提现了开放 ...

  9. C#设计模式之装饰者模式(Decorator Pattern)

    1.概述 装饰者模式,英文名叫做Decorator Pattern.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 2 ...

  10. Android设计模式之中的一个个样例让你彻底明确装饰者模式(Decorator Pattern)

    导读 这篇文章中我不会使用概念性文字来说明装饰者模式.由于通常概念性的问题都非常抽象.非常难懂.使得读者非常难明确究竟为什么要使用这样的设计模式.我们设计模式的诞生,肯定是前辈们在设计程序的时候遇到了 ...

随机推荐

  1. Linux 查找指定内容在哪个文件中

    在实际的工作中,忘记配置项放在哪个文件中时,可借助命令来查询. eg: 1.grep -r "查询内容"  文件目录    #这样查询出来的包括文件名+内容 grep -r -l ...

  2. 修改编码为utf8mb4 以支持emoji表情

    环境: 项目db的所有字符集都已经初始化为utf-8,如 status命令显示如下: Server characterset: utf8Db characterset: utf8Client char ...

  3. flask之视图函数从前端接收数据的方法

    一:从前端接收查询字符串  query-string 注意:get和post都可以在url后面添加查询字符串?a=1&b=2 测试工具:postman 1:get方式接收 视图函数 from ...

  4. linux下命令行执行Python程序提示no moudle,路径问题

    在ide中执行python程序,已经设置好项目路径中. 但是在cmd中执行程序,所在路径是python的搜索路径,如果涉及到import引用就会报类似ImportError: No module na ...

  5. [洛谷P3205] HNOI2010 合唱队

    问题描述 为了在即将到来的晚会上有更好的演出效果,作为AAA合唱队负责人的小A需要将合唱队的人根据他们的身高排出一个队形.假定合唱队一共N个人,第i个人的身高为Hi米(1000<=Hi<= ...

  6. hdu 1693 : Eat the Trees 【插头dp 入门】

    题目链接 题意: 给出一个n*m大小的01矩阵,在其中画线连成封闭图形,其中对每一个值为1的方格,线要恰好穿入穿出共两次,对每一个值为0的方格,所画线不能经过. 参考资料: <基于连通性状态压缩 ...

  7. Dubbo学习-4-dubbo简单案例-2-服务提供者和消费者配置

    在上一篇帖子的基础上,开始使用dubbo来实现RPC调用: 根据dubbo的架构图可知,需要做以下几件事情: 1.将服务提供者注册到注册中心(暴露服务) (1)引入dubbo依赖, 这里依赖2.6.2 ...

  8. CABasicAnimation来做心跳动画

    CABasicAnimation *anim = [CABasicAnimation animation]; anim.keyPath = @"transform.scale"; ...

  9. C#如何获取系统downloads和documents路径

    https://stackoverflow.com/questions/7672774/how-do-i-determine-the-windows-download-folder-path 如果你通 ...

  10. brdd 惰性执行 mapreduce 提取指定类型值 WebUi 作业信息 全局临时视图 pyspark scala spark 安装

    [rdd 惰性执行] 为了提高计算效率 spark 采用了哪些机制 1-rdd 基于分布式内存数据集进行运算 2-lazy evaluation  :惰性执行,即rdd的变换操作并不是在运行该代码时立 ...