读书人

组合设计模式理解多用组合少用继承的原

发布时间: 2012-10-27 10:42:26 作者: rapoo

结合设计模式理解多用组合少用继承的原则(转)
刚刚接触模式或者学习模式的人,经常会有这样的问题,为什么模式是成功的呢?很多人都会说模式是经验的积累,当然是正确的。可是经验为什么偏偏就证明了这种模式是正确的呢?这其中起用作的就是面向对象的基本原则。正是因为模式都或多或少的符合了面向对象的基本原则,所以模式才成为我们面向对象的设计和编码过程中不败的法则。那么什么是面向对象的基本原则呢?这就是我们将要一一讲到的问题。
单纯的讲到一个个的原则,就是那么的寥寥几句,非常的简单,但又是非常抽象的,难以理解。怎么办?
任何的理论,只要有生动的例子来讲解或证明,就能极大的帮助理解。所以我们准备从一个个的生动的例子来阐述我们的面向对象的基本原则。讲那些例子呢?上面我们说到,模式都是极大的遵从了这些原则的,那么我们把模式作为例子,来说明这些原则,不是我们信手拈来的吗?
现在我们说说其中的一个原则:对类的功能的扩展,要多用组合,少用继承
对于类的扩展,在面向对象的编程过程中,我们首先想到的是类的继承,由子类继承父类,从而完成了对子类功能的扩展。但是,面向对象的原则告诉我们,对类的功能的扩展要多用组合,而少用继承。其中的原因有以下几点:
第一、子类对父类的继承是全部的公有和受保护的继承,这使得子类可能继承了对子类无用甚至有害的父类的方法。换句话说,子类只希望继承父类的一部分方法,怎么办?
第二、实际的对象千变万化,如果每一类的对象都有他们自己的类,尽管这些类都继承了他们的父类,但有些时候还是会造成类的无限膨胀。
第三、 继承的子类,实际上需要编译期确定下来,这满足不了需要在运行内才能确定对象的情况。而组合却可以比继承灵活得多,可以在运行期才决定某个对象。
嗨!光说这么多一二三有什么用,我们就是想看看实际情况是不是像上面说的那样呢?还是来看看实际的例子吧!
现在我们需要这样一个HashMap,它除了能按常规的Map那样取值,如get(Object obj)。还能按位取值,像ArrayList那样,按存入对象对的先后顺序取值。
对于这样一个问题,我们首先想到的是做一个类,它继承了HashMap类,然后用一个ArrayList属性来保存存入的key,我们按key的位来取值,代码如下:

package decorator;interface Product {public double money();}//咖啡类:class Coffee implements Product {public double money() {    return 12;}}//加糖:class Sugar implements Product {private Product product;public Sugar(Product product) {    this.product = product;}public double money() {    return product.money() + 2;}}//加冰:class Ice implements Product {private Product product;public Ice(Product product) {    this.product = product;}public double money() {    return product.money() + 1.5;}}//加奶:class Milk implements Product {private Product product;public Milk(Product product) {    this.product = product;}public double money() {    return product.money() + 4.0;}}//加巧克力:class Chocolate implements Product {private Product product;public Chocolate(Product product) {    this.product = product;}public double money() {    return product.money() + 5.5;}}public class DecoratorModel{public static void main(String [] args){    Product coffee = new Coffee();    Product sugarCoffee = new Sugar(coffee);    Product sugarmilkCoffee = new Milk(sugarCoffee);    System.out.println("加糖咖啡:"+sugarCoffee.money());    System.out.println("加糖加奶咖啡:"+sugarmilkCoffee.money());}}

我们来看客户端的调用。
如果顾客想要黑咖啡,调用如下:
Product prod = new Coffee();
System.out.println(prod.money());
如果顾客需要加冰咖啡,调用如下:
Product prod = new Ice(new Coffee());
System.out.println(prod.money());
如果顾客想要加糖加冰加奶加巧克力咖啡,调用如下:
Product prod = new Chocolate(new Milk(new Ice(new Sugar())));
System.out.println(prod.money());
通过上面的例子,我们可以看到组合的又一个很优越的好处:能够在运行期创建新的对象。如上面我们的加冰咖啡,我们没有这个类,却能通过组合在运行期创建该对象,这的确大大的增加了我们程序的灵活性。
如果咖啡店的老板再要求你增加加压咖啡,你就不会再担心了,只给他增加了一个类就解决了所有的问题。

读书人网 >软件开发

热点推荐