- 浏览: 475287 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (1028)
- [发布至博客园首页] (826)
- [随笔分类]个人生活随笔 (14)
- [网站分类]首页候选区 (26)
- [网站分类]SharePoint (15)
- [网站分类]其他技术区 (6)
- [随笔分类]批处理技巧 (6)
- [随笔分类].net 2.0 (3)
- [随笔分类]SharePoint2007(MOSS2007) (0)
- [网站分类].NET新手区 (6)
- [网站分类]ASP.NET (6)
- [网站分类]架构设计 (18)
- [网站分类]程序人生 (2)
- [网站分类]SQL Server (2)
- WCF (3)
- 编程技巧 (2)
- 模式架构 (2)
- 分析设计 (4)
- 生活随笔 (0)
- 软件工程 (1)
- Android实例 (2)
最新评论
-
zilong0536:
楼主您好:
请问发表博文支持图片的功能怎么实现啊,一直没有思路 ...
新浪微博开放平台开发-android客户端(3) -
nicegege:
小弟 学习了
帮助中国移动设计10086的排队小模块 -
zl7824516:
用什么技术没说啊
通告(公告),消息(站内短信),提醒的设计:通告 -
virusswb:
源码下载: SinaWeibo2 源码下载之后,将后缀改为ra ...
新浪微博开放平台开发-android客户端(3) -
Jimmyxu0311:
找不到源码下载
新浪微博开放平台开发-android客户端(3)
接着上回的“针对接口编程,不针对实现编程”原则说。
假设开始我们设计了一个鸭子基类,发声、游泳和显示外观是鸭子类的功能。发声和游泳是通用的方法,放在基类实现,显示外观由于鸭子的不同而不同,放在继承类实现。可以设计出下面的类结构。
{
public virtual void Quack()
{
Console.WriteLine("我会嘎嘎叫");
}
public virtual void Swin()
{
Console.WriteLine("我会游泳");
}
public abstract void Display();
}
public class GreenHeadDuck : DuckBase
{
public override void Display()
{
Console.WriteLine("我是绿头鸭子");
}
}
public class RedHeadDuck : DuckBase
{
public override void Display()
{
Console.WriteLine("我是红头鸭子");
}
}
看起来还是比较OO的,利用了继承,复用了游泳和发声的代码。可是突然有一天需要创新,提出鸭子也应该可以飞,有人就提出来“这还不简单,在基类上加一个方法,鸭子都会飞了”。
{
public virtual void Quack()
{
Console.WriteLine("我会嘎嘎叫");
}
public virtual void Swin()
{
Console.WriteLine("我会游泳");
}
public abstract void Display();
public virtual void Fly()
{
Console.WriteLine("我是鸭子,我会飞");
}
}
貌似解决了鸭子会飞的问题。可是有一天问题来了,橡皮鸭子怎么会飞呢?它没有生命啊?
怎么回事呢?就是由于我们在基类添加的实现方法,继承类继承了这个方法,所有各种类型的鸭子都会飞了。可是还是有一些是不应该飞的,就像橡皮鸭子,木头鸭子等等。看来为了复用“飞”,而使用继承,结局并不理想。
当然了,也有解决的办法。既然是基类的方法,我们可以在继承类中重写它,如果不会飞就什么都不做?发声也出现了类似问题,不是每种鸭子都“嘎嘎”叫的,有的是“吱吱”发声,好吧,重写发声方法,以前的呢?都检查一遍,以后的新类型鸭子也需要注意叫声和是否会飞,好像有点麻烦?
{
public override void Display()
{
Console.WriteLine("我是橡皮鸭子");
}
public override void Quack()
{
Console.WriteLine("我会咯吱咯吱叫");
}
public override void Fly()
{
Console.WriteLine("我不会飞");
}
}
这样的继承造成了以下几个问题:
- 飞和叫的代码在多个子类中重复
- 运行的时候,行为不容易改变
- 很难知道鸭子的所有行为
- 改变牵一发,而动全身,其他类型的鸭子平白无故的多了一些不需要的功能。如果确实不要还要修改其他类型鸭子的代码。
有人又提出来了,利用接口吧。将会飞和发声写两个接口,然鸭子类去实现,实现了接口的就具有了这两个功能,没有实现的就不受影响。
{
public virtual void Swin()
{
Console.WriteLine("我会游泳");
}
public abstract void Display();
}
public class GreenHeadDuck : DuckBase,IFlyBehavior,IQuackBehavior
{
public override void Display()
{
Console.WriteLine("我是绿头鸭子");
}
public void Fly()
{
throw new NotImplementedException();
}
public void Quack()
{
throw new NotImplementedException();
}
}
public class RedHeadDuck : DuckBase, IFlyBehavior, IQuackBehavior
{
public override void Display()
{
Console.WriteLine("我是红头鸭子");
}
public void Quack()
{
throw new NotImplementedException();
}
public void Fly()
{
throw new NotImplementedException();
}
}
public class RubberDuck : DuckBase
{
public override void Display()
{
Console.WriteLine("我是橡皮鸭子");
}
public override void Quack()
{
Console.WriteLine("我会咯吱咯吱叫");
}
}
public interface IFlyBehavior
{
void Fly();
}
public interface IQuackBehavior
{
void Quack();
}
这样还是有点问题。就是很是很多的鸭子都会飞的,都会叫的,这部分的鸭子的飞和叫的代码就会重复,而且以前现有鸭子都需要检查一遍,都可能需要修改。接口虽然解决了只有继承才会具有相应的功能,但是因为接口没有实现,只有方法体的定义,所以造成了代码没有得到复用。表面看起来这两者好像是矛盾的。
引出另外一个设计原则:
找出应用中可能需要变化的地方,把他们独立出来,不要和那些不需要变化的代码混合在一起。把会变化的代码“封装”起来,好让修改的时候不影响其他部分。使得代码的修改对系统的影响最小,使得系统更具有弹性。
也就是说每次有新的需求,都会造成一部分代码的变化,将这部分变化的代码抽象出来,保持其他代码的稳定性。让系统的某部分修改不影响其他部分,这样其他部分就不需要测试,否则就需要全部测试一遍才可以保证代码的修改是正确的。
上面这个列子中的飞和叫是变化的地方,其他的没有太大变化。飞也有很多种方式,叫也有很多种“声音”。这两种叫做“行为”更好。原来的鸭子类,这两种行为是写死的,能否在初始化鸭子的时候,自己指定行为的方式呢?可以,开放一个属性,或者是一个方法,可以设置定义在鸭子基类中的行为就可以了,或者在构造函数中添加参数,指定行为。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BeautyCode.DesignPattern.Head.First
{
public abstract class DuckBase1
{
private IFlyBehavior1 _flyBehavior;
public IFlyBehavior1 FlyBehavior
{
get { return _flyBehavior; }
set { _flyBehavior = value; }
}
private IQuackBehavior1 _quackBehavior;
public IQuackBehavior1 QuackBehavior
{
get { return _quackBehavior; }
set { _quackBehavior = value; }
}
public virtual void Swin()
{
Console.WriteLine("我会游泳");
}
public void PerformQuack()
{
_quackBehavior.Quack();
}
public void PerformFly()
{
_flyBehavior.Fly();
}
public abstract void Display();
}
public class GreenHeadDuck1 : DuckBase1
{
public override void Display()
{
Console.WriteLine("我是绿头鸭子");
}
}
public class RedHeadDuck1 : DuckBase1
{
public override void Display()
{
Console.WriteLine("我是红头鸭子");
}
}
public class RubberDuck1 : DuckBase1
{
public override void Display()
{
Console.WriteLine("我是橡皮鸭子");
}
}
public interface IFlyBehavior1
{
void Fly();
}
public class FlyWithWings : IFlyBehavior1
{
public void Fly()
{
Console.WriteLine("有翅膀飞了");
}
}
public class FlyNoWay : IFlyBehavior1
{
public void Fly()
{
Console.WriteLine("没有也飞了");
}
}
public interface IQuackBehavior1
{
void Quack();
}
public class QuackA : IQuackBehavior1
{
public void Quack()
{
Console.WriteLine("嘎嘎");
}
}
public class Squeak : IQuackBehavior1
{
public void Quack()
{
Console.WriteLine("吱吱");
}
}
public class MuteQuack : IQuackBehavior1
{
public void Quack()
{
Console.WriteLine("哇哇");
}
}
}
调用代码
duck.FlyBehavior = new Head.First.FlyWithWings();
duck.PerformFly();
如果增加新的飞行方式,也只需要添加一个飞接口的实现,然后调用代码的duck.FlyBehavior = new Head.First.FlyWithWings();这一句进行修改就可以了,指定到新实现上面,具有了新的飞行方式。
发表评论
-
《深入浅出设计模式-中文版》读书笔记 策略模式(二)
2010-07-02 07:25 754接着上回的“针对接口编程,不针对实现编程”原则说。 假 ... -
NET 应用架构指导 V2 学习笔记(十二) 业务逻辑层的设计步骤
2010-06-01 00:07 459部署方面的考虑 当部署业务逻辑层的时候,一定要考虑生产 ... -
NET 应用架构指导 V2 学习笔记(二十一) 设计业务实体
2010-06-08 07:05 436概况 业务实体 ... -
分页存储过程(五)在MS SQL Server中打造更加准确,且有一点效率提升的的分页结果
2010-06-08 08:38 530以前的分页我都是 ... -
NET 应用架构指导 V2 学习笔记(二十二) 设计数据访问组件
2010-06-09 06:53 409概况 数据层组 ... -
Silverlight3+WCF遇到的问题(一):调试资源字符串不可用。密钥和参数通常提供足够的信息用以诊断该问题
2010-01-21 10:48 1405我在windows2003 R2上面开发Silve ... -
Silverlight3+WCF遇到的问题(二):wcf system.servicemodel.communicationexception
2010-01-28 13:43 615以前我访问的数据库都是一张表,没有关联,昨天添加了两张 ... -
Silverlight3系列(九)Silverlight 及其相关技术简介
2010-02-09 10:51 7301、Silverlight应用类型 •RIA Rich I ... -
【转载】利用SQL的charindex实现字符串数组和Split函数
2010-03-13 12:57 1083大家在T-SQL中使用substring的时候需要注意一点 ... -
根据总用量计算每种包装规格的购买量和总价
2010-03-23 12:36 446最近有这么一个需求,就是给出客户需要的总量,然后根据 ... -
根据总用量计算每种包装规格的购买量和总价
2010-03-23 12:36 257最近有这么一个需求,就是给出客户需要的总量,然后根据 ... -
Silverlight3+WCF遇到的问题(一):调试资源字符串不可用。密钥和参数通常提供足够的信息用以诊断该问题
2010-01-21 10:48 3237我在windows2003 R2上面开发Silve ... -
Silverlight3+WCF遇到的问题(二):wcf system.servicemodel.communicationexception
2010-01-28 13:43 702以前我访问的数据库都是一张表,没有关联,昨天添加了两张 ... -
Silverlight3系列(九)Silverlight 及其相关技术简介
2010-02-09 10:51 5851、Silverlight应用类型 •RIA Rich I ... -
【转载】利用SQL的charindex实现字符串数组和Split函数
2010-03-13 12:57 817大家在T-SQL中使用substring的时候需要注意一点 ... -
根据总用量计算每种包装规格的购买量和总价
2010-03-23 12:36 437最近有这么一个需求,就是给出客户需要的总量,然后根据 ... -
Silverlight3+WCF遇到的问题(一):调试资源字符串不可用。密钥和参数通常提供足够的信息用以诊断该问题
2010-01-21 10:48 2098我在windows2003 R2上面开发Silve ... -
Silverlight3+WCF遇到的问题(二):wcf system.servicemodel.communicationexception
2010-01-28 13:43 778以前我访问的数据库都是一张表,没有关联,昨天添加了两张 ... -
Silverlight3系列(九)Silverlight 及其相关技术简介
2010-02-09 10:51 6951、Silverlight应用类型 •RIA Rich I ... -
【转载】利用SQL的charindex实现字符串数组和Split函数
2010-03-13 12:57 944大家在T-SQL中使用substring的时候需要注意一点 ...
相关推荐
深入浅出MySQL-读书笔记byCZF深入浅出MySQL-读书笔记byCZF深入浅出MySQL-读书笔记byCZF
NULL 博文链接:https://bosshida.iteye.com/blog/1165049
深入浅出MFC读书笔记3 深入浅出MFC 读书笔记
学习笔记 深入浅出 设计模式,我是学习《深入浅出设计模式》的笔记,精华内容
《深入浅出设计模式》的编写运用许多最新的研究,包括神经生物学、认知科学以及学习理论,这使得《深入浅出设计模式》能够将这些设计模式深深地烙印在你的脑海中,不容易被遗忘。你将会更擅长于解决软件设计中的问题...
深入浅出MFC读书笔记2 深入浅出MFC 读书笔记
《深入浅出DPDK》全书读书笔记.pdf
《深入浅出Hibernate》读书笔记《深入浅出Hibernate》读书笔记《深入浅出Hibernate》读书笔记
23种设计模式---大牛笔记[汇编].pdf
Hadoop权威指南----读书笔记
学生读书笔记共享-学生读书笔记共享系统-学生读书笔记共享系统源码-学生读书笔记共享管理系统-学生读书笔记共享管理系统java代码-学生读书笔记共享系统设计与实现-基于springboot的学生读书笔记共享系统-基于Web的...
软考中级 - 软件设计师 - 专题复习笔记3软考中级 - 软件设计师 - 专题复习笔记3软考中级 - 软件设计师 - 专题复习笔记3软考中级 - 软件设计师 - 专题复习笔记3软考中级 - 软件设计师 - 专题复习笔记3软考中级 - 软件...
深入浅出MFC_简体中文版_侯捷 + 深入浅出MFC笔记(配合原书的好笔记)
详细介绍23种设计模式,结合gof设计模式来撰述,通过设计模式定义、组成、适用场景、以及示例等方式来呈现;资源来自设计模式深入浅出整理的笔记
深入浅出MFC读书笔记 MFC 深入浅出
候捷的经典之作,笔记是学习心得,希望大家喜欢
《深入浅出MFC》读书心得,我多年的笔记。
云的学习笔记-云的学习笔记系统-云的学习笔记系统源码-云的学习笔记管理系统-云的学习笔记管理系统java代码-云的学习笔记系统设计与实现-基于ssm的云的学习笔记系统-基于Web的云的学习笔记系统设计与实现-云的学习...