我有几个类代表一些测量数据,首先是<div class="wrapper">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
<div>11</div>
<div>12</div>
<div>13</div>
<div>14</div>
<div>15</div>
<div>16</div>
<div>17</div>
<div>18</div>
<div>19</div>
<div>20</div>
<div>21</div>
<div>22</div>
<div>23</div>
<div>24</div>
<div>25</div>
<div>26</div>
<div>27</div>
<div>28</div>
<div>29</div>
<div>30</div>
<div>31</div>
</div>
抽象类,派生ICut
和RoundCut
,如下所示:
SquareCut
当然它包含一些实现,但对于这个问题并不重要。 public abstract class ICut
{
}
public class RoundCut : ICut
{
DoSomeWithRoundCut(){}
}
public class SquareCut : ICut
{
DoSomeWithSquareCut(){}
}
是抽象类而不是接口,因为它本身就有一些实现。
然后,这里是代表ICut
数据集的类,同样是基础抽象ICut
和派生IRoll
和RoundRoll
:
SquareRoll
现在,我当然无法通过以下方式直接联系public abstract class IRoll
{
// list of measured cuts
public List<ICut> cuts;
// Create new cut
public abstract ICut CreateCut();
}
public class RoundRoll : IRoll
{
public RoundRoll ()
{
cuts = new List<RoundCut>();
}
public override ICut CreateCut()
{
RoundCut cut = new RoundCut();
cuts.Add(cut);
return cut;
}
}
public class SquareRoll : IRoll
{
public SquareRoll()
{
cuts = new List<SquareCut>();
}
public override ICut CreateCut()
{
SquareCut cut = new SquareCut();
cuts.Add(cut);
return cut;
}
}
或RoundCut
额外实施:
SquareCut
我不能同时使用:
IRoll roll = new RoundRoll();
roll.CreateCut();
roll.cuts[0].DoSomeWithRoundRoll();
因为我通常不知道(roll.cuts[0] as RoundCut).DoSomeWithRoundRoll();
派生IRoll
是哪个。
我正在重构一个庞大的项目,其中所有roll
个对象都是roll
类型,现在必须添加另一个。
也许我错过了某种合适的设计模式,我在高级OOP模式学习曲线的开头,我一直在考虑解决这个问题。< / p>
更新 经过多次实验,我意识到,与我的主要观点相反,我最终得到了@ The-First-Tiger的解决方案,并进行了一些改进。我创建了简单的工厂:
RoundRoll
所以我可以创建像:
// Cut factory
public static class CutFactory
{
// Get new cut by given shape type
public static ICut GetCut(RollShape shape)
{
switch (shape)
{
case RollShape.Round:
return new RoundCut();
case RollShape.Square:
return new SquareCut();
default:
throw new ArgumentException();
}
}
}
如果需要有不同的行为:
ICut cut = CutFactory.GetCut(roll.GetShape());
答案 0 :(得分:4)
解决此问题的一种方法是对IRoll
的类型ICut
进行通用:
public abstract class AbstractRoll<T> where T : ICut, new {
// list of measured cuts
public List<T> cuts = new List<T>();
// Create new cut
public T CreateCut() {
var res = new T();
curs.Add(res);
return res;
}
}
现在你可以这样做:
public class RoundRoll : AbstractRoll<RoundCut> {
...
}
public class SquareRoll : AbstractRoll<SquareCut> {
...
}
请注意,C#允许您通过将约束应用于泛型类型来将样板代码移动到基类。
现在唯一剩下的问题是AbstractRoll
不再是RoundRoll
和SquareRoll
的通用界面,因此您无法创建广告系列。
这个问题可以通过在IRoll
类之上添加一个非通用接口AbstractRoll
来解决,该接口具有所有卷的通用操作,并且也与卷的类型无关。 ICut
:
public interface IRoll {
IEnumerable<ICut> Cuts { get; }
... // add other useful methods here
}
public abstract class AbstractRoll<T> : IRoll where T : ICut, new {
...
public IEnumerable<ICut> Cuts {
get {
return curs.Cast<ICut>();
}
}
... // implement other useful methods here
}