c#实践了正确的面向对象技术

时间:2012-06-07 15:00:48

标签: c# .net oop

我有一些c#代码已经运行了一段时间了......我不得不说,虽然我理解OO原则的基础知识,但显然不止一种方法可以给猫皮肤(虽然我讨厌那个短语!)。

所以,我有一个基本抽象类,它充当基本数据服务类,如下所示(为简化阅读而简化):

public abstract class dataservice
{
    public enum OutputType : int { XmlTOJson = 0, Xml = 1, Json=2 }

    protected object SomeDBcall(string StoredProcedure)
    {
        // Just assume we are using SQLclient/DB access..
        object SomeReturnObjValue = db.ExecuteScalar(cmd);
        return SomeReturnObjValue;
    {
}

..所以基本上我可能在抽象类中有一些基本的DB检索/更新/删除调用..主要是因为我的应用程序中有任何数据库操作的基础。

所以现在我们有一个实现基类的类,比如我的客户类:

public class Customer : dataservice
{
    Public String CustomerDoSomething(string SomeDataEtc)
    {
        // Ok, so again for simplicity sake, we are going to use the base class to 
        // call a DB retrieve 
        object ReturningObj = SomeDBcall("my stored procedure");
        return ReturningObj.ToString();
    }
}

所以我想我的问题是:上面的方法是否“正常”使用?考虑到虚拟方法可能会被覆盖,如果需要,但在这种情况下我只希望基类使用受保护的方法来调用数据库操作。

非常感谢任何清晰度/指导!

5 个答案:

答案 0 :(得分:1)

当然,它是“ok”,但我认为基类没有理由abstractabstract类非常适合实现一些通用逻辑,并将其余部分留给派生类来实现。但是,你没有抽象/虚拟方法,所以我不明白这一点。

答案 1 :(得分:1)

也许您可以让您的抽象类具体化,并将其用作某种辅助类,它处理您需要的数据库相关内容。就示例代码所示,不需要具有多个数据库访问类,只需要不同的参数。

答案 2 :(得分:1)

您可能希望查看模板模式以定义基础(抽象或非抽象)类中的接口,其中定义的受保护虚拟挂钩可以在具体子类中重写。正如另一张海报所提到的,如果您只是打算为每个域区域添加数据库服务,您可能希望将基本数据库服务方法封装到辅助类中,而不是从数据库服务派生。

感谢@jgauffin质疑我的LSP违规声明。这是不正确的,已被删除。在很多情况下,保证通过子类扩展基类的公共接口。当然,通过这样做,在执行Y特定操作A()时,需要注意你有Y的实例而不是X或Z,假设Y和Z都来自X,其中Y加上新的公共方法A()和Z没有。

OP的上下文中的模板模式的示例将允许在子类内更好地封装自定义功能而无需扩展公共接口。但是,这仅在子类实例上没有外部影响时才有效,例如OP的SomeDataEtc参数。当实例是不可变的时,这种方法效果最好。

public abstract class DataService
{
    protected object myWidget = new Widget();
    public object SomeDataBaseCall(string storedProcedure)
    {

        DoSomeCustomThing();

        //do db stuff
        object SomeReturnObjValue = db.ExecuteScalar(storedProcedure);
        return SomeReturnObjValue;
    }

    protected void DoSomeCustomThing() {}
}


public class Customer : DataService
{
    override protected void DoSomeCustomThing()
    {
        // do your custom thing here
    }
}

此外,在OP的示例中,在派生类的新公共方法中使用委托调用基类的SomeDBCall方法来执行存储过程似乎是明智的。如果您对db访问方法进行冗余编码,则建议的继承没有任何好处。

正如其他地方也提到的那样,通过使用组合而不是继承来实现数据服务功能,你可能会更好。

答案 3 :(得分:1)

<强>概述

很多时候,你的“发展本身就会引导你”。

实际答案。

(1)您定义了一个基类“dataservice”,并且从该类开始,将基于其他几个类。你标记为“抽象”,这很好。这并不意味着自己拥有变量。

一些开发人员不会将该类标记为“抽象”,它不是强制性的,但是,这不是一个坏主意,而是一个“良好实践”,标记为“抽象”。

并且,将添加其他方法,由子类使用,可能覆盖,也许不是。

对于知道,这些方法是受保护的,并且anot意味着在对象之外使用,但是,通过其他方法。没关系。

也许,稍后,可能需要在课堂外使用某种方法,并且可能需要更改为公开。

(2)您添加了一个子类“Customer”,它是“DataService”的后代。您添加了一个必须在类外使用的方法,并标记为“public”,良好。

它只能用于此类,而不是父类。因此,不需要“虚拟”或“覆盖”。好。

(3)你的例子非常简单。 你做过的大多数事情,对我来说都很好

最后,当您添加更多代码时,事情可能会发生变化,例如私有的基类中的方法可能会公开,或者您可能会“重命名”或“重构”某个方法,例如“dosomething”,并找到最好是在基类中,或者不是。

<强>摘要

还有其他答案,提及,规则或概念。在我看来他们没问题,但是,跳过你正在学习使用O.O.P.的事实。更好。有些人只是试着“在一口大口吃蛋糕”,这不是一个好主意。

Pd积。 “你的皮肤可以兔子”,对我来说听起来更好。

干杯。

答案 4 :(得分:0)

没有。猜猜您的以下数据访问对象模式(DAO)。无论哪种方式,您的Customer都不是您的数据访问类。它使用一个类进行数据访问。我的意思是你的DAO应该支持组合而不是继承。

类似的东西:

public class Customer : IDataAccessObject
{
    public Customer()
    {
        _dataAccess = new DataAccess();
    }

    public string CustomerDoSomething(string SomeDataEtc)
    {
        object ReturningObj = _dataAccess.SomeDBcall("my stored procedure");
        return ReturningObj.ToString();
    }
}

为什么呢?你的对象只有一个责任,这意味着它更容易扩展和重构它们。

您可以阅读SOLID这是一些基本的编程原则。

由于您是.NET开发人员,我还建议您接受naming guidelines