如何正确设计许多sub-classes的组合?
How to propely design a combination of many sub-classes?
我有一个parentclass - Product
public abstract class Product {}
和扩展它的 3 sub-classes:
public class Vinyl extends Product {}
public class Book extends Product {}
public class Video extends Product {}
所有 sub-classes 使用其特定实现覆盖 preview()
方法。
现在,我有一个新的设计需求:我需要定义一个 combo item of vinyl
& book
其中还有一个 preview()
方法(是黑胶唱片和书籍的组合)。在说明中它说我可以创建 Interface\ class 字段成员或我想支持它的任何实现,但我不确定具体如何。
新设计是否也应该与 inheritance
一起实施,还是我应该更改当前设计?
Is the new design should also be implemented with inheritance or should I change the current design?
新的设计完全可以通过继承来实现。但是真正的问题是你会有太多的子类。您可以轻松地创建一个名为 VinylBook
的 Product
的新子类并完成它。但是当你必须引入另一个组合时会发生什么,比如 VinylVideo
。您还必须为此创建一个新的子类等等。
解决办法是结合使用继承和组合。 Composite 模式非常适合这个问题。根据维基百科:
The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
让我们先定义一个CompositeProduct
public class CompositeProduct` extends Product {
private List<Product> products;
public CompositeProduct(List<Product> products) { this.products = products }
public String preview() {
String previewText = "";
for(Product product : products) { previewText+=product.preview(); }
return preview;
}
}
您现在拥有了一个复合产品,它的行为就像是一个单一的产品,让您可以即时创建组合产品,而无需为每个组合创建新的子类。
如何即时创建产品的示例:
Book book = new Book();
Vinyl vinyl = new Vinyl();
List<Product> products = new List<>();
products.add(book);
products.add(vinyl);
CompositeProduct vinylBook = new CompositeProduct(products);
如果您正在考虑为您的产品动态添加额外的行为,您还可以看看 Decorator 模式。
我想提供一个替代方案,因为我对另一个解决方案不满意。(不要误会我的意思,它简单直接,而且 Composite 概念是一个非常好的学习概念,并且用户还提到装饰器模式,它真的很有用。
我对该解决方案的问题是你提供了产品(无论它们是什么)然后你能做什么?
让我们想象一下
public abstract class Product {
abstract void preview();
}
现在你的 CompositeProduct 太通用了,只能实现这样的东西
void preview(){
for(Product product : products) product.preview();
}
我敢打赌这不是你想要的。
我的替代方法是通过接口使用组合。关于域的更多细节,我不能说太多,所以我将举一个简单的例子。
什么是书?让我们想象一些可读的东西。
public interface Readable { void read(); }
public class Book extends Product implements Readable {}
什么是乙烯基?可显示
public interface Showable { void show(); }
public class Vinyl extends Product implements Showable {}
现在 BookVinyl 将只是
public class BookVinyl extends Product implements Readable, Showable { }
这会给你带来什么?那么,现在 BookVinyl 可以像书一样阅读,也可以像 Vinyl 一样展示。预览呢?它可以显示然后阅读或其他任何东西。
我有一个parentclass - Product
public abstract class Product {}
和扩展它的 3 sub-classes:
public class Vinyl extends Product {}
public class Book extends Product {}
public class Video extends Product {}
所有 sub-classes 使用其特定实现覆盖 preview()
方法。
现在,我有一个新的设计需求:我需要定义一个 combo item of vinyl
& book
其中还有一个 preview()
方法(是黑胶唱片和书籍的组合)。在说明中它说我可以创建 Interface\ class 字段成员或我想支持它的任何实现,但我不确定具体如何。
新设计是否也应该与 inheritance
一起实施,还是我应该更改当前设计?
Is the new design should also be implemented with inheritance or should I change the current design?
新的设计完全可以通过继承来实现。但是真正的问题是你会有太多的子类。您可以轻松地创建一个名为 VinylBook
的 Product
的新子类并完成它。但是当你必须引入另一个组合时会发生什么,比如 VinylVideo
。您还必须为此创建一个新的子类等等。
解决办法是结合使用继承和组合。 Composite 模式非常适合这个问题。根据维基百科:
The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
让我们先定义一个CompositeProduct
public class CompositeProduct` extends Product {
private List<Product> products;
public CompositeProduct(List<Product> products) { this.products = products }
public String preview() {
String previewText = "";
for(Product product : products) { previewText+=product.preview(); }
return preview;
}
}
您现在拥有了一个复合产品,它的行为就像是一个单一的产品,让您可以即时创建组合产品,而无需为每个组合创建新的子类。
如何即时创建产品的示例:
Book book = new Book();
Vinyl vinyl = new Vinyl();
List<Product> products = new List<>();
products.add(book);
products.add(vinyl);
CompositeProduct vinylBook = new CompositeProduct(products);
如果您正在考虑为您的产品动态添加额外的行为,您还可以看看 Decorator 模式。
我想提供一个替代方案,因为我对另一个解决方案不满意。(不要误会我的意思,它简单直接,而且 Composite 概念是一个非常好的学习概念,并且用户还提到装饰器模式,它真的很有用。
我对该解决方案的问题是你提供了产品(无论它们是什么)然后你能做什么?
让我们想象一下
public abstract class Product {
abstract void preview();
}
现在你的 CompositeProduct 太通用了,只能实现这样的东西
void preview(){
for(Product product : products) product.preview();
}
我敢打赌这不是你想要的。
我的替代方法是通过接口使用组合。关于域的更多细节,我不能说太多,所以我将举一个简单的例子。
什么是书?让我们想象一些可读的东西。
public interface Readable { void read(); }
public class Book extends Product implements Readable {}
什么是乙烯基?可显示
public interface Showable { void show(); }
public class Vinyl extends Product implements Showable {}
现在 BookVinyl 将只是
public class BookVinyl extends Product implements Readable, Showable { }
这会给你带来什么?那么,现在 BookVinyl 可以像书一样阅读,也可以像 Vinyl 一样展示。预览呢?它可以显示然后阅读或其他任何东西。