我在这里需要抽象类或接口吗(或者两者都不需要)?
我有一个仓库。 有时我想通过名称查找框位置,有时通过描述,有时通过 UPC,也许是其他东西,等等。这些查找方法中的每一个都调用相同的各种私有方法来查找信息以帮助定位数据。
例如,upc 调用私有方法来查找 rowid,name 也是如此,X 也是如此。所以我需要为所有这些方法提供该方法。 我可能会使用该 rowid 以某种方式查找货架位置(这只是一个示例。)
但我的问题是我应该有一个抽象类(或其他东西),因为我正在以不同的方式查找我的盒子。
换句话说,假设我的查找代码对于 UPC 和位置非常相似。 每个方法都可以调用某些内容(select * from xxxx where location =,或 select * from xxxx where upc =)。 我可以在同一个类中创建两个不同的方法
LocateByUPC(string upc)...
LocateByLocation(string location)...
LocateByDescription(string description)
...同样,这将在一个大类中是否有
任何理由我想要一个超级类来保存
abstract class MySuper
{
properties...
LocateBox(string mycriteria)...
}
然后继承它并创建第二个类来覆盖我需要哪个版本的 LocateBox 方法?
我不知道为什么我想这样做,除了它看起来很OOD,这实际上意味着如果我有充分的理由我想这样做。 但是,我知道没有任何优势。 我只是发现我的类变得越来越大,我只是稍微改变了方法的名称和一点代码,这让我认为继承可能会更好。
如果重要的话使用 C#。
编辑 - 如果我只给某人一个没有源代码但有类定义的 .dll,我会这样做吗? 班级定义。 会告诉我的属性等以及要重写的方法。
I have a warehouse. Sometimes I want to lookup a box location by a name, sometimes by a description, sometimes by a UPC, maybe something else, etc. Each of these lookup methods call the same various private methods to find information to help locate the data.
For example, upc calls a private method to find a rowid, so does name, so does X. So I need to have that method for all of them. I might use that rowid for some way to find a shelf location (it's just an example.)
But my question is should I have an abstract class (or something else) because I am looking up my box in different ways.
In other words, say my code for lookups is very similar for UPC and for location. Each method may call something with (select * from xxxx where location =, or select * from xxxx where upc =). I could just create two different methods in the same class
LocateByUPC(string upc)...
LocateByLocation(string location)...
LocateByDescription(string description)
... again, this would be in one big class
Would there be any reason that I would want a super class that would hold
abstract class MySuper
{
properties...
LocateBox(string mycriteria)...
}
and then inherit that and create a second class that overrides the LocateBox method for whichever version I need?
I don't know why I'd want to do this other than it looks OOD, which really means I'd like to do this if I have a good reason. But, I know of no advantage. I just find that my class gets bigger and bigger and I just slightly change the name of the methods and a little bit of code and it makes me think that inheritance might be better.
Using C# if that matters.
Edit - Would I do this if I only gave someone a .dll with no source but the class definition? The class def. would tell my properties, etc. and what methods to override.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
使用抽象类和接口都不会
简化协议,即您仍然会得到一堆 LocateXXX 方法,
我建议使用通用 Locate(string criteria) 方法作为基础,并且只为该方法定义专门的方法签名您知道自己会经常使用的; 如果您需要的话,泛型可以成为未来扩展的包罗万象的东西(并且依赖泛型可以简化编码和测试)
Neither
neither using an abstract class nor an interface will simplify the protocol, i.e. you will still end up with a bunch of LocateXXX methods
I would recommend having a generic Locate(string criteria) method as the basis, and only defining specialized method signatures for the ones you know you will use frequently; the generic can be a catch-all for future expansion in case you need it (and relying on the generic simplifies coding and testing)
听起来您可能想要实现称为模板方法的设计模式。 基本上,您可以将基类中的查找算法的轮廓定义为最终方法,并将公共代码放置在这些方法中。 对于根据类型需要不同行为的方法,只需让基类的最终方法调用子类中的受保护方法,并让每个子类型实现该行为。
您可以在网上查看一些资源,只需在谷歌中搜索模板方法设计模式即可。 希望它能解答您的问题。
It sounds like you might want to implement the design pattern called Template Method. Basically you would define the outline of the lookup algorithm in a base class as final methods, placing common code in those methods. For the methods that require different behavior depending on the type, simply have the base class' final methods call protected methods in the children, and have each child type implement that behavior.
You can take a look online at some resources, just do a google search for Template Method design pattern. Hopefully it will shed some light on your question.
当您有多个实现时,抽象会有所帮助。 并且为了面向未来(希望能够出现更新的实现)。 接口充当客户端和实现者之间的契约。 这是一个不变量。 实现可以自由地添加任意数量的方法。 您有这样的需求吗?
这有助于回答您的问题吗?
Abstraction helps when you have multiple implementations. And for future-proofing (hoping that a newer implementation will crop up). An interface acts as a contract between the client and the implementer. This is an invariant. Implementations are free to add any number of methods they wish to. Do you have any such needs?
Does that help answer your question?
您提出的(基本上)是策略模式。 我不喜欢链接到维基百科,但它至少是一个很好的起点。 看看它的优点和缺点,看看它是否对你有利。
我认为你确实没有必要这样做。 您可以简单地将 LocateBox 方法公开,并让它根据您想要执行的搜索调用私有帮助程序。 仅仅为了使用一些面向对象的设计原则而使类结构过于复杂通常是一个坏主意。 等到您找到它们的需求,然后进行适当的重构。 这将有助于指出什么是真正必要的,什么是浪费你的时间。
编辑:我想到的另一种方法是创建一个数据类,该数据类具有基于您可以搜索的各种内容的属性。 IE。 具有 UPC 等属性的 BoxSearchData 类,然后将其传递给 LocateBox() 并根据需要基于 null 属性构造查询。 这将帮助您稍后根据多个条件构建搜索。
What you are proposing is (basically) the Strategy pattern. I don't like to link to wikipedia, but its a good place to start at least. Take a look at the pros and cons and see if it would be beneficial to you.
I don't think there's really a need for you to do it this way. You can simply make the LocateBox method public and have it call private helpers based on which search you want to do. It's generally a bad idea to overly complicate your class structure just for the sake of using some OO design principles. Wait until you find a need for them, and then refactor appropriately. This will help point out what is really necessary and what is a waste of your time.
Edit: Another approach that I was thinking of would be to create a data class that has properties based on the various things you could search by. Ie. a BoxSearchData class that has properties such as UPC, etc, and then pass that to LocateBox() and construct the query as necessary based on the properties that are null. This would help you construct searches on multiple criteria later down the line.
在我看来这似乎没有必要。 只需拥有一个具有不同搜索功能的存储库即可。 然后只需在需要时使用您需要的功能即可。
但是,只有当您拥有对不同类型的搜索进行排队的工具时,界面部分才会变得有用。 然后你可以有一个工厂创建不同类型的搜索类,它们都实现一个接口。 此时,您可以枚举排队的搜索类,转换为接口,并执行虚拟函数并指向正确的搜索类型。 示例:
ReturnDataObject GetItem(object param);
另外,在提取数据时,接口还有其他用途。 这只是我想到的第一个例子。
It wouldn't seem necessary in my opinion. Just have a single repository that has the different search functions. Then just use the functions you need when they're needed.
However, the interface portion would only become useful if you have tools that are queueing up different types of searches. Then you could have a factory creating different types of Search classes that all implement an Interface. At which point you could enumerate through your queued Search classes, cast to the interface, and execute the function which would be virtual and point to the correct search type. Example:
ReturnDataObject GetItem(object param);
On a side note, there are other uses for interfaces when pulling data. That is just the first example that comes to mind.
当您仔细观察此示例时,您会发现只有用于查找的属性发生了变化。 当以面向对象的方式表示这一点时,您最终会得到一个我称之为“Lookup”的类(表示搜索,可能用 SQL,也可能用另一种查询语言:一个可以根据某些属性返回 rowId 并搜索的对象该属性的值。
真正的行为变化将出现在查询语言中。因此,如果您要创建一个抽象类或接口,则可以通过添加“来分隔属性和值的变化。 property”查询调用的参数。
When in this example you look closely, you see that only the property, used for lookup, changes. When representing this in an OO way, you end up with a class I would call "Lookup" (representing a search, maybe in SQL, maybe in another query language: an object that can return a rowId based on some property and searched-for value of that property.
The real behavioral change would be in the query language. So if you are to create an abstract class or an interface, it should serve that purpose. The concern of variation in property and value can be separated by adding a "property" argument to the query call.
当您需要大量数据时,抽象类很有用
子类之间的功能相同,例如在
购物车有多种付款方式可供选择,您可以
有一个定义通用支付方法的抽象类,并且
对于每次实际付款,子类都从超类继承
您想要支持的方式(PayPal、信用卡、帐户等)。 这
授权付款的机制对于每个人来说都是不同的
子类,但它们本质上都执行相同的功能 - 它们
验证用户可以证明他们可以支付商品或
有问题的服务。
接口有用的一个例子是当你有不相关的
需要在统一中提供一些类似功能的项目
方式。 例如,您可能有一个 CMS,其中文章存储在
数据库,但系统将它们缓存到光盘以及 HTML
直到数据库中的文章被修改,此时
物理文件将被删除,直到下次有人访问该物理文件
复制到数据库中。 您的 CMS 可能还支持以下功能:
用户上传图像、PDF 等以存储在光盘上以便访问,
但你绝对不希望这些文件作为副本被删除
光盘代表文件本身,而不是缓存版本。 在这个
在这种情况下,您可以创建一个可缓存接口来说明什么方法
缓存到光盘的类需要实现,而保留它
交给类本身来实现它们。 这更有意义
几乎肯定需要代表不同类型数据的类
以不同的方式实施他们的缓存方案(如果有)。
每个允许缓存的类都将被定义为 Class
实现了 Cacheable,您可以在其中检查
你的代码。 经验不足的编码人员可能会测试对象的类
他们通过获取课程并处理结果来进行工作
带有一个大的 switch 语句。 这不是正确的方法,因为
这意味着您假设某些类对象实现
某些功能,如果您向系统添加一个新类
需要修改软件中的每个 switch 语句以将其纳入
帐户。 如果你实现一个接口,你可以测试一个对象是否
使用instanceof关键字实现该接口。
这种方法更好,因为它消除了 switch 语句并且
从而使您的软件更易于维护。 如果你添加一个新类
对于也实现自己的缓存方案的系统,那么您
只需要声明它实现了 Cacheable 即可。 作为界面
要求所有实现它的类声明指定的方法
在接口中,您可以确定任何实现了
Cacheable会提供一定的方法供你使用。 你的代码
不需要知道类如何实现这些方法,只需知道
它确实实现了它们。
这些概念解释起来比实际学习要困难一些
恐怕要使用,希望我已经很好地理解了基本思想
足以让你自己弄清楚它们。
An abstract class is useful when you need a substantial amount of
functionality to be identical across the subclasses, for example in a
shopping cart with multiple methods of payment available, you could
have an abstract class which defines a generic payment method, and
have subclasses inherit from the superclass for each actual payment
method you want to support (paypal, credit card, account, etc). The
mechanics of how a payment is authorized would be different for each
subclass, but they all perform essentially the same function - they
validate that a user can prove that they can pay for the goods or
services in question.
An example of where an interface is useful is where you have unrelated
items that need to provide some similar functionality in a uniform
way. For example, you might have a CMS where articles are stored in a
database, but where the system caches them to disc as well as HTML
pages until the article in the database is modified, at which point
the physical file is deleted until the next time someone access the
copy in the database. Your CMS might also support the ability for
users to upload images, PDFs, etc to be stored for access on the disc,
but you definitely don't want these files to be deleted as the copy on
the disc represents the file itself and not a cached version. In this
case, you could create a Cacheable interface that says what methods a
class which is cached to disc needs to implement, while leaving it up
to the class itself to implement them. This makes more sense as
classes that represent different kinds of data almost certainly need
to implement their caching scheme (if any) differently.
Every class that allows caching would be defined as Class
implements Cacheable, which is something you can then check for in
your code. Less experienced coders might test the class of an object
they are working with by getting the class and processing the result
with a big switch statement. This isn't the correct approach because
it means that you're assuming that certain classes objects implement
certain functionality, and if you add a new class to the system you
need to modify every switch statement in your software to take it into
account. If yo uimplement an interface you can test if an object
implements that interface with the instanceof keyword.
This approach is better because it eliminates the switch statement and
thus makes your software easier to maintain. If you add a new class
to the system that also implements its own caching scheme then you
just need to declare that it implements Cacheable. As the interface
requires all classes to implement it to declare the methods specified
in the interface you can be sure that any class that implements
Cacheable will provide certain methods for you to use. Your code
doesn't need to know how the class implements these methods, just that
it does implement them.
These concepts are somewhat trickier to explain than to actually learn
to use I'm afraid, hopefully I've got the basic ideas across well
enough for you to figure them out for yourself.
显然这里的多态实体就是约束。 使用字符串是实现相同目的的快速而肮脏的方法,但是您的类型系统完全脱离了循环,并且垃圾字符串值对于输入来说与有意义的约束规范一样有效。
所以,
等等
。
Obviously the entity that is polymorphic here is the constraint. Using string is the quick and dirty way of achieving the same but your type system is completely out of the loop and garbage string values will be just as valid for input as meaningful constraint specs.
So,
and
etc.