Confusion with Factory pattern regarding Liskov’s Substitution Principle, code maintainability and Unit Testing?

I have a confusion regarding Factory Pattern there are basically two ways You can implement that.

Approach 1:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public interface IProductFactory
{
IProduct GetProductA();
IProduct GetProductB();
IProduct GetProductC();
}
public class ProductFactory : IProductFactory
{
public IProduct GetProductA()
{
//some implementation goes here
}
public IProduct GetProductB()
{
//some implementation goes here
}
public IProduct GetProductC()
{
//some implementation goes here
}
}
</code>
<code>public interface IProductFactory { IProduct GetProductA(); IProduct GetProductB(); IProduct GetProductC(); } public class ProductFactory : IProductFactory { public IProduct GetProductA() { //some implementation goes here } public IProduct GetProductB() { //some implementation goes here } public IProduct GetProductC() { //some implementation goes here } } </code>
public interface IProductFactory
{
    IProduct GetProductA();
    IProduct GetProductB();
    IProduct GetProductC();
}

public class ProductFactory : IProductFactory
{
    public IProduct GetProductA()
    {
        //some implementation goes here
    }
    public IProduct GetProductB()
    {
        //some implementation goes here
    }
    public IProduct GetProductC()
    {
        //some implementation goes here
    }
}

Approach 2:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public enum ProductType
{
ProductA = 1,
ProductB = 2,
ProductC = 3
}
public interface IProductFactory
{
IProduct GetProduct(ProductType productType);
}
public class ProductFactory : IProductFactory
{
public IProduct GetProduct(ProductType productType)
{
switch (productType)
{
case ProductType.ProductA:
//return IProduct with specific implementation
break;
case ProductType.ProductB:
//return IProduct with specific implementation
break;
case ProductType.ProductC:
//return IProduct with specific implementation
break;
default:
//return null
}
}
}
</code>
<code>public enum ProductType { ProductA = 1, ProductB = 2, ProductC = 3 } public interface IProductFactory { IProduct GetProduct(ProductType productType); } public class ProductFactory : IProductFactory { public IProduct GetProduct(ProductType productType) { switch (productType) { case ProductType.ProductA: //return IProduct with specific implementation break; case ProductType.ProductB: //return IProduct with specific implementation break; case ProductType.ProductC: //return IProduct with specific implementation break; default: //return null } } } </code>
public enum ProductType
{
    ProductA = 1,
    ProductB = 2,
    ProductC = 3
}

public interface IProductFactory
{
    IProduct GetProduct(ProductType productType);
}

public class ProductFactory : IProductFactory
{
    public IProduct GetProduct(ProductType productType)
    {
        switch (productType)
        {
            case ProductType.ProductA:
                //return IProduct with specific implementation
                break;
            case ProductType.ProductB:
                //return IProduct with specific implementation
                break;
            case ProductType.ProductC:
                //return IProduct with specific implementation
                break;
            default:
            //return null
        }
    }
}

Pros of both approaches

Approach 1:

  1. benefit of compile time checks that the implementation class will be
    forced to provide the corresponding methods.

Approach 2:

  1. Implementation will have a benefit of shorter no. of lines of code.
  2. Interface does not become fragile, it won’t change as the new
    products keep on adding.

Cons of both approaches

Approach 1:

  1. Lines of code becomes large.
  2. As more number of Products are implemented, the interface changes
    and hence it is hard to follow Liskov’s Substitution Principle.

Approach 2:

  1. Since it is hiding internal details of GetProduct, it is hard to
    tell what the Factory will return when a specific type of enum is
    passed.
  2. You might get into run time exceptions

I am still struggling to decide on which approach to use?


Note: I am only aware of these two approaches, there might be different approaches also.

2

Both approaches break Liskov Substitution Principle. Correct implementation will look smth. like:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public interface IProductFactory
{
IProduct GetProduct();
}
public class Product1Factory : IProductFactory
{
public IProduct GetProduct()
{
return new Product1(); //configure instance here
}
}
public class Product2Factory : IProductFactory
{
public IProduct GetProduct()
{
return new Product2(); //configure instance here
}
}
public class Product3Factory : IProductFactory
{
public IProduct GetProduct() //configure instance here
{
return new Product3();
}
}
</code>
<code>public interface IProductFactory { IProduct GetProduct(); } public class Product1Factory : IProductFactory { public IProduct GetProduct() { return new Product1(); //configure instance here } } public class Product2Factory : IProductFactory { public IProduct GetProduct() { return new Product2(); //configure instance here } } public class Product3Factory : IProductFactory { public IProduct GetProduct() //configure instance here { return new Product3(); } } </code>
public interface IProductFactory
{
    IProduct GetProduct();
}

public class Product1Factory : IProductFactory
{
    public IProduct GetProduct()
    {
        return new Product1(); //configure instance here
    }
}

public class Product2Factory : IProductFactory
{
    public IProduct GetProduct()
    {
        return new Product2(); //configure instance here
    }
}

public class Product3Factory : IProductFactory
{
    public IProduct GetProduct() //configure instance here
    {
        return new Product3();
    }
}

5

Approach 2 is the classical Factory Pattern. This pattern is nothing to do with LSP. To ensure LSP is not violated in the client programs, you need to carefully design IProduct interface in such a way that the client program that is operating on IProduct would continue to operate without any modification irrespective of the concrete product that actually implements IProduct. If, you observe you are violating LSP redesign the interfaces.

For example it may be better to create one interface for a category of products if these categories differ in the way client communicates with them.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public interface IPerfume
{
//Methods specific perfume products
}
public interface IAutomobile
{
//Methods specific to automobiles
}
</code>
<code>public interface IPerfume { //Methods specific perfume products } public interface IAutomobile { //Methods specific to automobiles } </code>
public interface IPerfume
{
    //Methods specific perfume products
}

public interface IAutomobile
{
    //Methods specific to automobiles
}

Then, you define one factory for each category of products. PerfumeFactory to create perfume products and AutomobileFactory to create automobiles.

The example may not sound fancy but that is all I can think of now.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Confusion with Factory pattern regarding Liskov’s Substitution Principle, code maintainability and Unit Testing?

I have a confusion regarding Factory Pattern there are basically two ways You can implement that.

Approach 1:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public interface IProductFactory
{
IProduct GetProductA();
IProduct GetProductB();
IProduct GetProductC();
}
public class ProductFactory : IProductFactory
{
public IProduct GetProductA()
{
//some implementation goes here
}
public IProduct GetProductB()
{
//some implementation goes here
}
public IProduct GetProductC()
{
//some implementation goes here
}
}
</code>
<code>public interface IProductFactory { IProduct GetProductA(); IProduct GetProductB(); IProduct GetProductC(); } public class ProductFactory : IProductFactory { public IProduct GetProductA() { //some implementation goes here } public IProduct GetProductB() { //some implementation goes here } public IProduct GetProductC() { //some implementation goes here } } </code>
public interface IProductFactory
{
    IProduct GetProductA();
    IProduct GetProductB();
    IProduct GetProductC();
}

public class ProductFactory : IProductFactory
{
    public IProduct GetProductA()
    {
        //some implementation goes here
    }
    public IProduct GetProductB()
    {
        //some implementation goes here
    }
    public IProduct GetProductC()
    {
        //some implementation goes here
    }
}

Approach 2:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public enum ProductType
{
ProductA = 1,
ProductB = 2,
ProductC = 3
}
public interface IProductFactory
{
IProduct GetProduct(ProductType productType);
}
public class ProductFactory : IProductFactory
{
public IProduct GetProduct(ProductType productType)
{
switch (productType)
{
case ProductType.ProductA:
//return IProduct with specific implementation
break;
case ProductType.ProductB:
//return IProduct with specific implementation
break;
case ProductType.ProductC:
//return IProduct with specific implementation
break;
default:
//return null
}
}
}
</code>
<code>public enum ProductType { ProductA = 1, ProductB = 2, ProductC = 3 } public interface IProductFactory { IProduct GetProduct(ProductType productType); } public class ProductFactory : IProductFactory { public IProduct GetProduct(ProductType productType) { switch (productType) { case ProductType.ProductA: //return IProduct with specific implementation break; case ProductType.ProductB: //return IProduct with specific implementation break; case ProductType.ProductC: //return IProduct with specific implementation break; default: //return null } } } </code>
public enum ProductType
{
    ProductA = 1,
    ProductB = 2,
    ProductC = 3
}

public interface IProductFactory
{
    IProduct GetProduct(ProductType productType);
}

public class ProductFactory : IProductFactory
{
    public IProduct GetProduct(ProductType productType)
    {
        switch (productType)
        {
            case ProductType.ProductA:
                //return IProduct with specific implementation
                break;
            case ProductType.ProductB:
                //return IProduct with specific implementation
                break;
            case ProductType.ProductC:
                //return IProduct with specific implementation
                break;
            default:
            //return null
        }
    }
}

Pros of both approaches

Approach 1:

  1. benefit of compile time checks that the implementation class will be
    forced to provide the corresponding methods.

Approach 2:

  1. Implementation will have a benefit of shorter no. of lines of code.
  2. Interface does not become fragile, it won’t change as the new
    products keep on adding.

Cons of both approaches

Approach 1:

  1. Lines of code becomes large.
  2. As more number of Products are implemented, the interface changes
    and hence it is hard to follow Liskov’s Substitution Principle.

Approach 2:

  1. Since it is hiding internal details of GetProduct, it is hard to
    tell what the Factory will return when a specific type of enum is
    passed.
  2. You might get into run time exceptions

I am still struggling to decide on which approach to use?


Note: I am only aware of these two approaches, there might be different approaches also.

2

Both approaches break Liskov Substitution Principle. Correct implementation will look smth. like:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public interface IProductFactory
{
IProduct GetProduct();
}
public class Product1Factory : IProductFactory
{
public IProduct GetProduct()
{
return new Product1(); //configure instance here
}
}
public class Product2Factory : IProductFactory
{
public IProduct GetProduct()
{
return new Product2(); //configure instance here
}
}
public class Product3Factory : IProductFactory
{
public IProduct GetProduct() //configure instance here
{
return new Product3();
}
}
</code>
<code>public interface IProductFactory { IProduct GetProduct(); } public class Product1Factory : IProductFactory { public IProduct GetProduct() { return new Product1(); //configure instance here } } public class Product2Factory : IProductFactory { public IProduct GetProduct() { return new Product2(); //configure instance here } } public class Product3Factory : IProductFactory { public IProduct GetProduct() //configure instance here { return new Product3(); } } </code>
public interface IProductFactory
{
    IProduct GetProduct();
}

public class Product1Factory : IProductFactory
{
    public IProduct GetProduct()
    {
        return new Product1(); //configure instance here
    }
}

public class Product2Factory : IProductFactory
{
    public IProduct GetProduct()
    {
        return new Product2(); //configure instance here
    }
}

public class Product3Factory : IProductFactory
{
    public IProduct GetProduct() //configure instance here
    {
        return new Product3();
    }
}

5

Approach 2 is the classical Factory Pattern. This pattern is nothing to do with LSP. To ensure LSP is not violated in the client programs, you need to carefully design IProduct interface in such a way that the client program that is operating on IProduct would continue to operate without any modification irrespective of the concrete product that actually implements IProduct. If, you observe you are violating LSP redesign the interfaces.

For example it may be better to create one interface for a category of products if these categories differ in the way client communicates with them.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public interface IPerfume
{
//Methods specific perfume products
}
public interface IAutomobile
{
//Methods specific to automobiles
}
</code>
<code>public interface IPerfume { //Methods specific perfume products } public interface IAutomobile { //Methods specific to automobiles } </code>
public interface IPerfume
{
    //Methods specific perfume products
}

public interface IAutomobile
{
    //Methods specific to automobiles
}

Then, you define one factory for each category of products. PerfumeFactory to create perfume products and AutomobileFactory to create automobiles.

The example may not sound fancy but that is all I can think of now.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật