第 2 章 面向对象设计原则
-
B A C D D C
-
C
-
D
-
D
-
“封装变化点”可对应“开闭原则”,“对接口进行编程”可对应“依赖倒转原则”,“多使用组合,
而不是继承”可对应“合成复用原则”。 -
类的粒度需满足单一职责原则,接口的粒度需满足接口隔离原则。
-
在面向对象设计中,正方形不能作为长方形的子类,具体分析过程如下:
class Rectangle //长方形
{
private double width;
private double height;
public Rectangle(double width,double height)
{
this.width=width;
this.height=height;
}
public double getHeight()
{
return height;
}
public void setHeight(double height)
{
this.height = height;
}
public double getWidth()
{
return width;
}
public void setWidth(double width)
{
this.width = width;
5
}
}
class Square extends Rectangle //正方形
{
public Square(double size)
{
super(size,size);
}
public void setHeight(double height)
{
super.setHeight(height);
super.setWidth(height);
}
public void setWidth(double width)
{
super.setHeight(width);
super.setWidth(width);
}
}
class Client
{
public static void main(String args[])
{
Rectangle r;
r = new Square(0.0);
r.setWidth(5.0);
r.setWidth(10.00);
double area = calculateArea(r);
if(50.00==area)
{
System.out.println("这是长方形或长方形的子类!");
}
else
{
System.out.println("这不是长方形!");
}
}
public static double calculateArea(Rectangle r)
{
return r.getHeight() * r.getWidth();
}
}
由代码输出可以得知,我们在客户端代码中使用长方形类来定义正方形对象,将输出“这
不是长方形!”,即将正方形作为长方形的子类,在使用正方形替换长方形之后正方形已经
不再是长方形,接受基类对象的地方接受子类对象时出现问题,违反了里氏代换原则,因此
从面向对象的角度分析,正方形不是长方形的子类,它们都可以作为四边形类的子类。关于
该问题的进一步讨论,大家可以参考其他相关资料,如 Bertrand Meyer 的基于契约设计
(Design By Contract),在长方形的契约(Contract)中,长方形的长和宽是可以独立变化的,但是正方形破坏了该契约。
- 重构方案如下所示:
在本重构方案中,将笔的大小和颜色设计为两个继承结构,两者可以独立变化,根据依
赖倒转原则,建立一个抽象的关联关系,将颜色对象注入到画笔中;再根据合成复用原则,
画笔在保持原有方法的同时还可以调用颜色类的方法,保持原有性质不变。如果需要增加一
种新的画笔或增加一种新的颜色,只需对应增加一个具体类即可,且客户端可以针对高层类
Pen 和 Color 编程,在运行时再注入具体的子类对象,系统具有良好的可扩展性,满足开闭
原则。(注:本重构方案即为 桥接模式)