2

我有一个对象,假设是他们调用 web 方法后返回到客户端的数据。

        // NewData1.cs
        public NewData1(Concrete1 con)
        {
            ID = con.ID;
            var results= con.listOfResults();

                var something= con.GetSomething();
                Something = new List<Somethings>();

                con.DoSomething();
            }

            // NewData2.cs
            public NewData2(Concrete2 con)
            {
                ID = con.ID;
                var results= con.listOfResults();

                var something= con.GetSomething();
                Something = new List<Somethings>();

                con.DoSomething();
            }

            // NewData3.cs
            public NewData3(Concrete3 con)
            {
                ID = con.ID;
                var results= con.listOfResults();

                var something= con.GetSomething();
                Something = new List<Somethings>();

                con.DoSomething();
            }

正如你所看到的,这些类做同样的事情(这不是我的代码..我想改变它)。唯一不同的是具体类型 (1,2,3) 在调用其方法时执行不同的逻辑。

您是否知道一种将这些类减少为一个类但仍使它们中的每一个具有其特殊逻辑而不相同的方法?

4

4 回答 4

1

如果您的Concrete1,Concrete2Concrete3类共享相同的方法,您可以将其提取到接口中并让它们实现它:

// an interface is simply a contract
interface ICanGetSomething
{
    int ID { get; }
    List<Result> ListOfResults();
    Something GetSomething();
}

// your concrete classes should all implement the same interface
class Concrete1 : ICanGetSomething { ... }
class Concrete2 : ICanGetSomething { ... }
class Concrete3 : ICanGetSomething { ... }

这样,您只需要一个方法来处理所有这些:

public void NewData(ICanGetSomething con)
{
    ID = con.ID;
    var results = con.ListOfResults();
    var something = con.GetSomething();
    ...
}

如果它们也共享相同的功能,您还可以使用通用抽象类来重用所有通用代码:

abstract class Base : ICanGetSomething { ... }

// your concrete classes should all inherit from the same base class
class Concrete1 : Base { ... }
class Concrete2 : Base { ... }
class Concrete3 : Base { ... }

无论哪种方式,我都建议使用接口来定义合约。由于 C# 不支持多重继承,因此您不希望强制所有具体实现从单个基类派生(除非有必要)。这仍然意味着您将在有共享功能的地方使用继承,但您的NewData方法应该接受参数的接口,而不是基类。

于 2013-08-20T14:44:27.407 回答
0

You want an abstract base class:

public abstract class BaseClass
{
    // Use protected fields to store data that only this class and derived
    // classes can access.
    protected List<Something> storedSomethings;

    //Define an abstract method signature for methods that the concrete classes
    // have very different implementations for:
    public abstract List<Something>GetSomethings();

    //Use a virtual method for methods that are identical or similar on 
    //the concrete classes:
    public virtual void AddSomethings(List<Something> addList)
    {
        storedSomethings.Add(addList);
    }
}

Then your concrete classes are implemented like so:

public class Concrete1 : BaseClass
{

    public override List<Something> GetSomethings()
    {
    //actual logic here
    }

    //override any other abstract methods
}

public class Concrete2 : BaseClass
{

    public override List<Something> GetSomethings()
    {
    //actual logic here
    }

    //override any other abstract methods
}

Concrete3 is slightly different, it needs to filter on addsomethings:

public class Concrete3 : BaseClass
{

    public override List<Something> GetSomethings()
    {
    //actual logic here
    }

    //override any other abstract methods

    //For some reason this class doesn't want all somethings, so it overrides
    // the base method and filters before calling the base method
    public override AddSomethings(List<Something> addList)
    {
        base.AddSomethings(addList.Where(s => s.Condition == false));
    }
}

Now, you should only need one newdata class:

public newdata(BaseClass classInstance)
{
    //As long as every method you want to call is defined on BaseClass
    // and implemented on the concrete classes, you can just do:
    classInstance.GetSomething();
}
于 2013-08-20T14:39:50.300 回答
0

如果所有 3 个派生类都具有完全相同的签名,则可以从 Concrete 创建一个抽象基类。

基类:

public abstract class AbstractBaseClass
{
    public long ID { get; set; }
    public abstract List<string> ListOfResults();
    public abstract string GetSomething();
    public abstract void DoSomething();
}

你的具体派生自它:

public class Concrete1 : AbstractBaseClass
{
    public override List<string> ListOfResults()
    {
        // Logic
    }

    public override string GetSomething()
    {
        // Logic
    }

    public override void DoSomething()
    {
        // Logic
    }
}

将参数设置为基类:

public void NewData(AbstractBaseClass abs)
{
    ID = abs.ID;

    var results= abs.listOfResults();
    var something= abs.GetSomething();
    abs.DoSomething();
}

您现在可以这样做,例如:

NewData data = new NewData(new Concrete1());

NewData 构造函数中的所有调用都将定向到 Concrete1 子类。

如果只能拥有一个 NewData 实例,则可以在需要时使用Stategy 模式来更改具体类。

于 2013-08-20T14:47:51.693 回答
0

创建以下基类。

public class Concrete
{
    public int ID { get; set; }

    public virtual something GetSomething()
    {

    }

    public virtual void DoSomething()
    {

    }
}

让你的concrete1、concrete2 等类扩展Concrete。如果需要,这些类将能够覆盖 GetSomething 方法。那么你只需要其中之一。

public NewData2(Concrete con)
{
    ID = con.ID;
    var results= con.listOfResults();

    var something= con.GetSomething();
    Something = new List<Somethings>();

    con.DoSomething();
}
于 2013-08-20T14:43:53.760 回答