您的位置:首页 > 其它

开发模式学习笔记之——OCP 开放-封闭原则

2009-02-25 22:42 417 查看
我们需要在标准GUI上绘制贺和正方形的应用程序,圆和正方形必须要按照某种特定的顺序来绘制。

下面的例子中,分别使用了结构化的方案,以及实现OCP原则的演化过程。什么也不说了,看代码吧。

1、结构化方案

class __过程化方案
{
//一但需要增加新形状,所以用到此枚举的地方全部需要重新编译和布署!
enum ShapType
{
circle,square
}

class Shape
{
public ShapType itsType=0;
}

//----------------------------
class Circle : Shape
{
public double itsRadius=0;
public Point itsCenter=new Point();
}

void DrawCircle(Circle circle)
{ }

//-----------------------------
class Square : Shape
{
public double itsSide=0;
public Point itsTopLeft=new Point();
}

void DrawSquare(Square square)
{ }

//----------------------------
//一但需要增加新的类型,则此类需要改动,而不是扩展!
void DrawAllShapes(List<Shape> shapeList)
{
foreach (Shape shape in shapeList)
{
switch (shape.itsType)
{
case ShapType.circle:
DrawCircle((Circle)shape);
break;
case ShapType.square:
DrawSquare((Square)shape);
break;
default:
break;
}
}
}

/* 所有需要使用到类型的其它地方,全部需用使用类似的switch语句
* 而一但增加新形状,所有这些地方全部需要改动
* */

}


2、OCP解决方案

class __OCP解决方案
{
public interface IShape
{
void Draw();
}

public class Square : IShape
{
#region IShape 成员

public void Draw()
{
throw new Exception("The method or operation is not implemented.");
}

#endregion
}

public class Circle : IShape
{
#region IShape 成员

public void Draw()
{
throw new Exception("The method or operation is not implemented.");
}

#endregion
}

public void DrawAllShapes(List<IShape> shapes)
{
foreach (IShape shape in shapes)
{
shape.Draw();
}
}

//--------------------
//如果增加一个Triangle,则新增这样的类,其余地方全部不做改变
public class Triangle : IShape
{
#region IShape 成员

public void Draw()
{
throw new Exception("The method or operation is not implemented.");
}

#endregion
}
}


3、需要先画所有圆的解决方案

class __需要先画所有圆的解决方案
{
//这是一个错误的解决方案,将IShape接口扩展增加IComparabe接口
public interface IShape : IComparable
{
void Draw();
}

public class Circle:IShape
{
public void Draw()
{
throw new Exception("The method or operation is not implemented.");
}

public int CompareTo(object obj)
{
if (obj is Square)
return -1;
else
return 0;
}
}

public class Square : IShape
{
public void Draw()
{
throw new Exception("The method or operation is not implemented.");
}

public int CompareTo(object obj)
{
throw new Exception("The method or operation is not implemented.");
}
}

//然后重写DrawAllShapes方法
public void DrawAllShapes(List<IShape> shapes)
{
shapes.Sort();          //先排序再绘制
foreach (IShape shape in shapes)
{
shape.Draw();
}
}

//----------------
//这种解决方案并没有解决过程化方案遇到的问题
//就是一但增加新的形状,所有的类的CompareTo方法全部都要改动
//那么解决方法就是:将变化的地方提取出来!!!!(见下一个类)
}


4、使用所谓"数据驱动"的方法获得封闭性

//使用所谓"数据驱动"的方法获得封闭性
class __需要先画所有圆的解决方案_正确方案
{
public class ShapeCompare:IComparer
{
private static Hashtable priorities = new Hashtable();

static ShapeCompare()
{
priorities.Add(typeof(Circle), 1);
priorities.Add(typeof(Square), 2);
//priorities.Add(typeof(Triangle), 1);  //此行为后来新增的部分,其它代码则全部保持不变
}

private int PriorityFor(Type type)
{
if (priorities.Contains(type))
return (int)priorities[type];
else
return 0;
}

int IComparer.Compare(object x, object y)
{
int priority1 = PriorityFor(x.GetType());
int priority2 = PriorityFor(y.GetType());
return priority1.CompareTo(priority2);
}
}

//重写DrawAllShapes
public void DrawAllShapes(ArrayList shapes)
{
shapes.Sort((new ShapeCompare()));          //先排序再绘制
foreach (IShape shape in shapes)
{
shape.Draw();
}
}

/* 这样,增加三角形的时候,只需新增一个三角形类就OK了
* 其它所有的代码都不用动了!
* */

public interface IShape
{
void Draw();
}

public class Square : IShape
{
public void Draw()
{
throw new Exception("The method or operation is not implemented.");
}
}

public class Circle : IShape
{
public void Draw()
{
throw new Exception("The method or operation is not implemented.");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: