软件实体(类,模块,函数等)应该是可扩展的,但是不可修改
优点:通过扩展已有软件系统,可以提供新的行为,以满足对软件的新的需求,使变化中的软件有一定的适应性和灵活性。已有软件模块,特别是最重要的抽象层模块不能再修改,这使变化中的软件系统有一定的稳定性和延续性。
下边举一个从不符合ocp到符合ocp的例子,shap示例在很多书中提到,我们这里用它来阐明ocp。不符合ocp的代码如下:
class
Circle
... {
private double Radius;
public double radius
...{
get ...{ return Radius; }
set ...{ Radius = value; }
}
private double x;
public double X
...{
get ...{ return x; }
set ...{ x = value; }
}
private double y;
public double Y
...{
get ...{ return y; }
set ...{ y = value; }
}
public void Draw()
...{
Console.WriteLine("画圆");
}
}
class Square
... {
private double x;
public double X
...{
get ...{ return x; }
set ...{ x = value; }
}
private double y;
public double Y
...{
get ...{ return y; }
set ...{ y = value; }
}
private double lenth;
public double Lenth
...{
get ...{ return lenth; }
set ...{ lenth = value; }
}
private double width;
public double Width
...{
get ...{ return width; }
set ...{ width = value; }
}
public void Draw()
...{
Console.WriteLine("画正方形");
}
}
static void Main( string [] args)
... {
List<object> list = new List<object>();
list.Add(new Circle());
list.Add(new Square());
DrawAll(list);
}
static void DrawAll(List < object > list)
... {
foreach (object var in list)
...{
if (var is Circle)
...{
((Circle)var).Draw();
}
else
...{
((Square)var).Draw();
}
}
}
... {
private double Radius;
public double radius
...{
get ...{ return Radius; }
set ...{ Radius = value; }
}
private double x;
public double X
...{
get ...{ return x; }
set ...{ x = value; }
}
private double y;
public double Y
...{
get ...{ return y; }
set ...{ y = value; }
}
public void Draw()
...{
Console.WriteLine("画圆");
}
}
class Square
... {
private double x;
public double X
...{
get ...{ return x; }
set ...{ x = value; }
}
private double y;
public double Y
...{
get ...{ return y; }
set ...{ y = value; }
}
private double lenth;
public double Lenth
...{
get ...{ return lenth; }
set ...{ lenth = value; }
}
private double width;
public double Width
...{
get ...{ return width; }
set ...{ width = value; }
}
public void Draw()
...{
Console.WriteLine("画正方形");
}
}
static void Main( string [] args)
... {
List<object> list = new List<object>();
list.Add(new Circle());
list.Add(new Square());
DrawAll(list);
}
static void DrawAll(List < object > list)
... {
foreach (object var in list)
...{
if (var is Circle)
...{
((Circle)var).Draw();
}
else
...{
((Square)var).Draw();
}
}
}
以上代码的问题是当增加新的图形时DrawAll函数要做比较大的修改工作,这很容易影响原本可以正常工作的部分,因为增加图形的变化可能性非常大,而且实际上当从画一种图形到画两种图形时我们已经发现了问题,我们不能再错过改成错误的机会,我们要对以上源代码进行大规模的重构。
interface
IShap
... {
void Draw();
}
class Circle : IShap
... {
private double Radius;
public double radius
...{
get ...{ return Radius; }
set ...{ Radius = value; }
}
private double x;
public double X
...{
get ...{ return x; }
set ...{ x = value; }
}
private double y;
public double Y
...{
get ...{ return y; }
set ...{ y = value; }
}
public void Draw()
...{
Console.WriteLine("画圆");
}
}
class Square : IShap
... {
private double x;
public double X
...{
get ...{ return x; }
set ...{ x = value; }
}
private double y;
public double Y
...{
get ...{ return y; }
set ...{ y = value; }
}
private double lenth;
public double Lenth
...{
get ...{ return lenth; }
set ...{ lenth = value; }
}
private double width;
public double Width
...{
get ...{ return width; }
set ...{ width = value; }
}
public void Draw()
...{
Console.WriteLine("画正方形");
}
}
static void Main( string [] args)
... {
List<IShap> list = new List<IShap>();
list.Add(new Circle());
list.Add(new Square());
DrawAllShap(list);
}
static void DrawAllShap(List < IShap > list)
... {
foreach (IShap shap in list)
...{
shap.Draw();
}
}
... {
void Draw();
}
class Circle : IShap
... {
private double Radius;
public double radius
...{
get ...{ return Radius; }
set ...{ Radius = value; }
}
private double x;
public double X
...{
get ...{ return x; }
set ...{ x = value; }
}
private double y;
public double Y
...{
get ...{ return y; }
set ...{ y = value; }
}
public void Draw()
...{
Console.WriteLine("画圆");
}
}
class Square : IShap
... {
private double x;
public double X
...{
get ...{ return x; }
set ...{ x = value; }
}
private double y;
public double Y
...{
get ...{ return y; }
set ...{ y = value; }
}
private double lenth;
public double Lenth
...{
get ...{ return lenth; }
set ...{ lenth = value; }
}
private double width;
public double Width
...{
get ...{ return width; }
set ...{ width = value; }
}
public void Draw()
...{
Console.WriteLine("画正方形");
}
}
static void Main( string [] args)
... {
List<IShap> list = new List<IShap>();
list.Add(new Circle());
list.Add(new Square());
DrawAllShap(list);
}
static void DrawAllShap(List < IShap > list)
... {
foreach (IShap shap in list)
...{
shap.Draw();
}
}
以上代码在增加新的图形的时候只需实现Ishap接口,根本就不需要修改DrawAllShap函数,这样DrawAllShap函数就符合了ocp。
当画图时需要按某种顺序时,这种设计就没办法符合ocp原则了,如下更改是在需要顺序支持德尔符合ocp设计的代码(表格法)
class
CompareShap:IComparer
<
IShap
>
... {
Dictionary<Type, int> table = new Dictionary<Type, int>();
public CompareShap()
...{
table.Add(typeof(Circle), 1);
table.Add(typeof(Square), 2);
}
private int PriorityFor(Type type)
...{
if (table.ContainsKey(type))
...{
return table[type];
}
else
...{
return 0;
}
}
IComparer 成员#region IComparer<IShap> 成员
public int Compare(IShap x, IShap y)
...{
int p1 = PriorityFor(x.GetType());
int p2 = PriorityFor(y.GetType());
return p1.CompareTo(p2);
}
#endregion
}
... {
Dictionary<Type, int> table = new Dictionary<Type, int>();
public CompareShap()
...{
table.Add(typeof(Circle), 1);
table.Add(typeof(Square), 2);
}
private int PriorityFor(Type type)
...{
if (table.ContainsKey(type))
...{
return table[type];
}
else
...{
return 0;
}
}
IComparer 成员#region IComparer<IShap> 成员
public int Compare(IShap x, IShap y)
...{
int p1 = PriorityFor(x.GetType());
int p2 = PriorityFor(y.GetType());
return p1.CompareTo(p2);
}
#endregion
}
调用程序:
class
Program
... {
static void Main(string[] args)
...{
List<IShap> list = new List<IShap>();
list.Add(new Circle());
list.Add(new Square());
DrawAllShap(list);
}
static void DrawAllShap(List<IShap> list)
...{
list.Sort(new CompareShap());
foreach (IShap shap in list)
...{
shap.Draw();
}
}
}
... {
static void Main(string[] args)
...{
List<IShap> list = new List<IShap>();
list.Add(new Circle());
list.Add(new Square());
DrawAllShap(list);
}
static void DrawAllShap(List<IShap> list)
...{
list.Sort(new CompareShap());
foreach (IShap shap in list)
...{
shap.Draw();
}
}
}