博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式学习(一):多用组合少用继承(C#)
阅读量:6495 次
发布时间:2019-06-24

本文共 4036 字,大约阅读时间需要 13 分钟。

《深入浅出设计模式》学习笔记第一章

原始需求和设计

事情是这样开始的,公司需要做一套程序,鸭子,设计如下:

一个鸭子父类,多个派生类,三个可override的方法。

第一次需求变更

我们要会飞的鸭子!!!!!

所以我们做了如下的更改:

父类加了fly方法,嗯,所有的鸭子都会飞了,需求实现!

问题发生了,因为不是所有的鸭子都会飞

我们可以在派生类中把父类的fly方法中的内容覆盖掉,那么这个鸭子就不会飞了!

那么问题又来了,如果再出现几个新型鸭子都不会飞,是不是每个都得覆盖一遍fly方法啊????

也许,可以用接口?

把每个方法都做成接口,如图:

这是超笨的方法,如果一些鸭子的飞行方式发生变化,那么得改多少个类啊。。。

现在的情况是:

继承不行,因为鸭子的行为(需求)在子类里面不断变化,而使用接口又无法进行复用。

幸好,面向对象软件开发有这样一个原则:

找出应用中可能需要变化的地方,把它们独立起来,不要和那些不需要发生变化的代码混在一起。

这句话另一种思考方式就是:把变化的部分取出并封装起来,以便以后可以轻松的改动或扩展,而不影响其他部分

所以我们应该把鸭子的行为都提取出来。

根据需求,我们知道鸭子的fly和quack行为经常发生变化,所以我们现在的设计是这样的:

 

设计原则:

针对接口编程而不是针对实现编程。

 这是变化的部分,对于Fly和Quack分别定义接口。

namespace DesignPatterns.Intro.Bases{    public interface IFlyBehavior    {        void Fly();    }}namespace DesignPatterns.Intro.Bases{    public interface IQuackBehavior    {        void Quack();    }}

然后实现几种类型的Fly和Quack:

namespace DesignPatterns.Intro.Derives{    public class Squeak: IQuackBehavior    {        public void Quack()        {            Console.WriteLine("吱吱");        }    }}namespace DesignPatterns.Intro.Derives{    public class NormalQuack: IQuackBehavior    {        public void Quack()        {            Console.WriteLine("呱呱");        }    }}namespace DesignPatterns.Intro.Derives{    public class MuteQuack: IQuackBehavior    {        public void Quack()        {            Console.WriteLine("---------");        }    }}

整合鸭子的行为

让我们来定义鸭子:

namespace ConsoleApp2.Bases{    public abstract class Duck    {        private readonly IFlyBehavior _flyBehavior;        private readonly IQuackBehavior _quackBehavior;        protected Duck(IFlyBehavior flyBehavior = null, IQuackBehavior quackBehavior = null)        {            _flyBehavior = flyBehavior ?? new FlyNoWay();            _quackBehavior = quackBehavior ?? new MuteQuack();        }        public abstract void Display();        public void PerformFly()        {            _flyBehavior.Fly();        }        public void PerformQuack()        {            _quackBehavior.Quack();        }        public void Swim()        {            Console.WriteLine("所有的鸭子都会游泳");        }    }}

这是鸭子的抽象类。

建立实际的鸭子:

namespace ConsoleApp2.Derives{    public class MallardDuck: Duck    {        public MallardDuck(IFlyBehavior flyBehavior = null, IQuackBehavior quackBehavior = null) : base(flyBehavior, quackBehavior)        {        }        public override void Display()        {            Console.WriteLine("我是个野鸭...");        }    }}

 

测试鸭子

namespace ConsoleApp2{    class Program    {        static void Main(string[] args)        {            var duck = new MallardDuck(new FlyNoWay(), new NormalQuack());            duck.PerformFly();            duck.PerformQuack();            duck.Display();            Console.ReadLine();        }    }}

这时,需求终于完成了!

我们的鸭子根据传入的Fly和Quack实现类不同而具有不同的效果!

需求又变了,要求鸭子的行为可以随时改变

这时,我们需要动态设定行为,我们只需要加入Set方法即可:

 

Duck最新的代码是:

namespace ConsoleApp2.Bases{    public abstract class Duck    {        public IFlyBehavior FlyBehavior { private get; set; }        public IQuackBehavior QuackBehavior { private get; set; }        protected Duck(IFlyBehavior flyBehavior = null, IQuackBehavior quackBehavior = null)        {            FlyBehavior = flyBehavior ?? new FlyNoWay();            QuackBehavior = quackBehavior ?? new MuteQuack();        }        public abstract void Display();        public void PerformFly()        {            FlyBehavior.Fly();        }        public void PerformQuack()        {            QuackBehavior.Quack();        }        public void Swim()        {            Console.WriteLine("所有的鸭子都会游泳");        }    }}

测试效果:

namespace ConsoleApp2{    class Program    {        static void Main(string[] args)        {            var duck = new MallardDuck();            duck.PerformFly();            duck.PerformQuack();            duck.Display();            duck.FlyBehavior = new FlyWithWings();            duck.QuackBehavior = new Squeak();            duck.PerformFly();            duck.PerformQuack();            Console.ReadLine();        }    }}

需求完成!!!

最终结构如下:

设计原则:多用组合,少用继承

下面是我的关于ASP.NET Core Web API相关技术的公众号--草根专栏:

转载地址:http://iruyo.baihongyu.com/

你可能感兴趣的文章
Windows10 远程桌面连接失败,报CredSSP加密oracle修正错误解决办法
查看>>
egit在pull的时候出错
查看>>
Zabbix 中使用 Percona Monitoring Plugins 监控 MySQL
查看>>
我的友情链接
查看>>
5.Struts2-Struts标签
查看>>
各种技术综合总结(一)
查看>>
Filter案例用户自动登录学习笔记
查看>>
阿里云内网和公共NTP服务器
查看>>
c++ 正则表达式邮箱
查看>>
C 提高1 内存四区 变量本质 栈开口方向 指针铁律1
查看>>
QT windows平台安装
查看>>
Outlook 2003 邮件不能显示图片
查看>>
1+1*2+1*2*3+1*2*3*n数列的求和算法
查看>>
异常模拟测试 -- 场景抽象及解决方案
查看>>
Gradle之旅-can not find tools.jar问题解决
查看>>
JavaScript_navigator
查看>>
apache配置文件详解
查看>>
linux下echo的使用总结
查看>>
EDM营销学堂:高效提升营销邮件点击率的技巧
查看>>
ORACLE 11G静默安装配置分解
查看>>