继承——若只如初见

  相信在开始学习C++、Java、C#等面向对象语言的时候,你总是先接触到继承概念。

  老师或书籍总是通过继承让我们相信面向对象开发可以大大节省编码量,因为需要一个新特性的类型时,扩展并添加一两个方法就可以了。

  但工作几年后,我们自己逐渐发现继承不总是那么好,尤其当你的设计处于继承结构的底层的时候,每次修改总是牵扯面太大,不愿意或者不敢去修改这些内容。然后,我们借鉴Delphi早期类库设计的技巧,把底层类的大部分方法都定义为虚方法,结果随着项目代码规模的扩大,开发期最灵活的设计往往到了生产环境却造成最难排查的问题。

  最后,我们接受了基于接口编程的思路。设计模式也一直倡导组合优于继承的概念,尤其在C#Java等语言彻底不支持多继承之后,我们才把目光从“堆积”类变成“捆绑”接口。

如果在一开始学习的时候就有人提示一下多好。

 

    继承若只如初见。


贸易电子化,技术全球化
posted @ 2011-06-06 12:13 蜡笔小王 阅读(1393) 评论(14) 编辑 收藏

 回复 引用 查看   
#1楼[楼主] 2011-06-06 12:20 蜡笔小王      
现在除了接口外,还有很多扩展是通过Attribute、Annotation完成。
 回复 引用 查看   
#2楼 2011-06-06 12:25 AfritXia      
现在持有“继承最好用”观点的人,还大有人在
 回复 引用 查看   
#3楼[楼主] 2011-06-06 13:48 蜡笔小王      
@AfritXia

是啊。

感觉现在有不少软件像“快餐”,而且完成后也不用自己维护很多年,所以开发的时候不太关注以后怎么修改和维护。
这时候,用继承省事。

 回复 引用 查看   
#4楼 2011-06-06 16:59 thestarmm      
hi 楼主,
现在用到的方式如下:
Interface IA{}
Class B:IA{}
Class C:B{}
Class D:B{}
...

IA c=new C();
IA d=new D();
...
B中含有一点abstract方法和virtual方法,C,D...中overwrite,能提示一下如何改观吗?谢谢

 回复 引用 查看   
#5楼[楼主] 2011-06-06 17:26 蜡笔小王      
@thestarmm

1、如果B中的abstract方法和virtual方法都是为绕着简化IA某些方法实现的——不需要改观
现有的这个设计也是大多数框架的做法。

2、如果B中的abstract方法和virtual方法不是围绕着IA展开的,也就是说有了新的职责,建议把他们抽象出一个新的IX

变成,
Interface IA{}

Class B:IA, IX{}
或者
Class B:IA
{
public IX X{get;set;}
}

 回复 引用 查看   
#6楼 2011-06-07 09:45 snowjake      
不顶对不起广大的乡亲父老。。。。。。
 回复 引用 查看   
#7楼 2011-06-09 23:26 StephenJu      
可以通过接口来访问原有对象,并限制组合对象和内部对象之间的依赖程度。即使组合可以提供同样的功能,去无法实现多态。若是觉得多态比不可少,应该选用白盒重用.....

最近在研读王老师的书,受益匪浅!

 回复 引用 查看   
#8楼[楼主] 2011-06-10 10:45 蜡笔小王      
@StephenJu

谢谢鼓励。
上一版写的时候,很多文字太“绕”。
最近,我在出版社编辑的帮助下,对新版的行文正在进行第4遍修改。

等样章出来后,也请多多批评
有些新的实现技巧也请帮忙把关,看看是否适用、实用。


祝好。

 回复 引用   
#9楼 2011-06-15 23:48 qwertasdfg[未注册用户]
按3步查询出某种产品列表(不同类型产品需要有这个共同的功能)
步骤1单选:选择单个产品条件(如产品使用面积)
步骤2单选:选择单个产品条件(如产品颜色)
步骤3多选:选择多个产品功能(如:节能、智能温控等)
请问如上需求用策略模式实现可行吗?还有什么更好的方法实现吗?
非常感谢!

 回复 引用   
#10楼 2011-06-15 23:50 qwertasdfg[未注册用户]
粗略代码如下,代码有点,还请老师帮忙指点指点,非常感谢!
public enum QueryType
{
KongTiao = 0,
Washer,
}
public interface IStep3Query<TProduct, TFilter>
where TProduct : class
where TFilter : class
{
QueryType QueryCategory { get; }
IList<TProduct> Query(QueryType queryType, TFilter filter);
}

public class WasherStep3Query : IStep3Query<Washer, WasherFilter>
{
public QueryType QueryCategory
{
get { return QueryType.Washer; }
}

public IList<Washer> Query(QueryType queryType, WasherFilter filter)
{
return null;
}
}

/// <summary>
/// 洗衣机
/// </summary>
public class Washer
{
}

 回复 引用   
#11楼 2011-06-15 23:51 qwertasdfg[未注册用户]
public abstract class FilterBase<TFuncParam> where TFuncParam : class
{
public abstract string Filter1 { get; set; }
public abstract string Filter2 { get; set; }
public abstract IList<TFuncParam> Filter3 { get; set; }
}

public class WasherFilter : FilterBase<string>
{
public override string Filter1
{
get{略}
set{略}
}

public override string Filter2
{
get{略}
set{略}
}

public override IList<string> Filter3
{
get{略}
set{略}
}
}

public interface IConsultant<TProduct, TFilter>
where TProduct : class
where TFilter : class
{
List<TProduct> GetProductList(QueryType queryType);
}

public class Consultant<TProduct, TFilter> : IConsultant<TProduct, TFilter>
where TProduct : class
where TFilter : class
{
private IDictionary<QueryType, IStep3Query<TProduct, TFilter>> CallInfo { get; set; }
public Consultant(IEnumerable<IStep3Query<TProduct, TFilter>> querys)
{
CallInfo = querys.ToDictionary(p => p.QueryCategory);
}

public List<TProduct> GetProductList(QueryType queryCategory)
{
return null;
}
}

 回复 引用 查看   
#12楼[楼主] 2011-06-16 16:13 蜡笔小王      
@qwertasdfg

你好。
你的问题用策略模式没有问题,不过在具体实现的时候建议面向工程应用做些工作。

1、抽象看,第一次筛选和第N次筛选的条件是一样的,
也就是给出一个 wahingMachine,然后返回是否符合筛选条件,

所以所有筛选条件(策略)可以用.NET自己的
Predicate<WashingMachine>,定义。
他是个委托,第二章就提过,.NET的所有委托都是具有Multicast特性的
所以

2、所有查询条件,不管是筛选1次还是筛选了N次,都可以合并到一个Predicate<WashingMachine>中。

所以最后的示例结构可以这样:

class WashingMachine
{
public double Price { get; set; }
public double Area { get; set; }
public string Brand { get; set; }
public Color Color { get; set; }
public bool HasSmartController { get; set; }
}

/// <summary>
/// 数据
/// </summary>
IEnumerable<WashingMachine> washingMachines = null;

[TestMethod]
public void TestDelegateStrategyQuery()
{
Predicate<WashingMachine> filter = (x) => (x.Area > 10); // 条件1
filter += (x) => (x.Price > 200); // 条件2
filter += (x) => (x.HasSmartController); // 条件3


var result = washingMachines.Where(x=>filter(x));
}


 回复 引用 查看   
#13楼[楼主] 2011-06-16 16:14 蜡笔小王      
@qwertasdfg

不过你有多少个查询条件、筛选多少次,最后都合并到一个
Predicate<WashingMachine> filter
中,然后执行下.Where筛选就可以了。

:)

我们可以就这个问题继续讨论。
祝好

 回复 引用   
#14楼 2011-06-18 23:34 qwertasdfg[未注册用户]
谢谢您的回复,非常感谢。

委托是个好东西!
你说的对,其实结果要的就是个where条件,用Predicate委托实现是简单明了。

发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 2073584 3ucDPdaVgk0=