为了在java中设计API,我提出了以下模式来满足这里列出的某些要求
示例代码如下:
package external;
import internal.AbstractProduct;
public final class Product extends AbstractProduct{
protected Product(int a, int b){
super(a,b);
}
@Override
public int result(){
return super.result();
}
}
public class ProductFactory {
public static Product createProudct(int a, int b){
return new Product(a, b);
}
}
和内部类如下:
package internal;
public abstract class AbstractProduct {
private final AbstractProduct impl;
protected AbstractProduct(int a, int b){
impl = new ProductImpl(a, b);
}
protected AbstractProduct(){
impl = null;
}
protected int result(){
return impl.result();
}
}
class ProductImpl extends AbstractProduct{
private int a;
private int b;
ProductImpl(int a, int b){
this.a = a;
this.b = b;
}
@Override
protected int result(){
return a*b;
}
}
虽然它工作正常并且具有适当的访问级别,但我只具有设计模式或API设计的初级技能,所以我似乎很难发现可能的故障。那么这有什么问题吗?还是一些已经实践过的模式?
答案 0 :(得分:4)
您尝试实施的唯一设计模式是ProductFactory
类中的Factory Method。这是唯一想要的设计模式。
由于您当前的代码非常不灵活,整体甚至可以被视为anti-pattern,更具体地说:
Product
才能执行ProductImpl#result
。Product
仅使用super
次来电。int
乘法。(可能更多......)
说明:您的工厂方法模式非常不灵活。请注意Product
类是public
,但有一个protected
构造函数(甚至标记为final
类,奇数:为什么要{ {1}}类上的方法可以从不继承?),这意味着protected
至少应与ProductFactory
位于同一个包中。
正如我在其他评论中直接提到的那样,如果您解释功能要求以获得更好,更准确的设计帮助,那就太棒了。
IMO为了了解设计模式,最好去现实世界的例子,而不是继续在网上越来越多地阅读它们,然后开始练习。我强烈推荐BalusC(Java和Java EE专家)的这个Q / A:Examples of GoF Design Patterns in Java's core libraries
答案 1 :(得分:0)
为什么这样?
protected AbstractProduct(){
impl = null;
}
这会在调用result()
时导致NullPointerException。
我也看不到AbstractProduct
和ProductImpl
的观点。只需将代码放在Product
。
如果只有一个实现,但是如果您打算在将来实施,那么我也会问你为什么需要一个ProductFactory
。那就没关系。
答案 2 :(得分:0)
如果是我,我就这样分解:
package external;
import internal.InternalProduct;
import internal.ProductImpl;
public final class Product {
private final InternalProduct internalProduct;
Product(final InternalProduct internalProduct) {
this.internalProduct = internalProduct;
assert this.internalProduct != null;
}
public int result() {
return this.internalProduct.result();
}
}
public class ProductFactory {
public static Product createProduct(final int a, final int b) {
return new Product(new ProductImpl(a, b));
}
}
面向内部的包裹内容为:
package internal;
public interface InternalProduct {
int result();
}
public final class ProductImpl implements InternalProduct {
private final int a;
private final int b;
public ProductImpl(final int a, final int b) {
this.a = a;
this.b = b;
}
@Override
protected int result() {
return a * b;
}
}
您不需要抽象课程,并且您肯定不希望Product
扩展它。你应该在这里使用封装。这可以保护您的Product
类免受内部界面的更改 - 除非您选择方法,否则可以在不Product
获取方法的情况下添加方法。
如果最终实现了更多的实现并且您想要一个抽象父级,您可以选择是否每个实现扩展它,因为您的external
包依赖于该接口。