Dealing with the principles of SOLID some questions arose in understanding. Namely, is it ok to change the class constructor if there is a need to extend the class functionality? Often there is a problem with the fact that it is necessary to inject an additional class into the class in order to add functionality.
It seems to me that in this case the principle of openness / closeness is violated. The question is how to avoid violation of this principle with the following example.
There is an interface
public interface ShopFactory { List<Discount> getDiscounts(); List<Sale> getSales(); } And its implementation (I can’t change the interface, because anyone who connected my library to my project can implement this interface).
public class CountableDefaultShopFactory implements ShopFactory { Counter discountsCounter; Counter salesCounter; public CountableDefaultShopFactory(Counter discountsCounter, Counter salesCounter) { this.discountsCounter = discountsCounter; this.salesCounter = salesCounter; } @Override List<Discount> getDiscounts() { discountsCounter.count(); return Discount.defaultDiscounts(); } @Override List<Sale> getSales() { salesCounter.count(); return Sale.defaultSales(); } } Looks pretty simple. CountableDefaultShopFactory implements ShopFactory , overrides two methods, and accepts two Counter objects in the constructor that will be used to count the number of times the method has been called. As a result, each method returns a result by calling a static method.
Now suppose you need to add functionality to this class and it will return another list of objects of type Coupon . Only he will take them not from the static method of the Coupon class, but because of the database for example. Suppose I have a DAO class that returns this data.
So my class takes the following form
public class CountableDefaultShopFactory implements ShopFactory { Counter discountsCounter; Counter salesCounter; Counter couponsCounter; CouponDAO couponDAO; public DefaultShopFactory(Counter discountsCounter, Counter salesCounter, Counter couponsCounter, CouponDAO couponDAO) { this.discountsCounter = discountsCounter; this.salesCounter = salesCounter; this.couponsCounter = couponsCounter; this.couponDAO = couponDAO; } @Override List<Discount> getDiscounts() { discountsCounter.count(); return Discount.defaultDiscounts(); } @Override List<Sale> getSales() { salesCounter.count(); return Sale.defaultSales(); } @Override List<Coupon> getCoupons() { couponsCounter.count(); return couponDAO.getDefaultCoupons(); } } As you can see, we had to modify the constructor, namely to add more couponsCounter parameters (which I think is normal) and couponDAO .
For good I think that the class CountableDefaultShopFactory should not know anything about the DAO layer and then the actual question arises as to how best to do this? And how would you do that? Perhaps there are ready-made patterns for such cases, I unfortunately did not find a similar one.
Thank you in advance.
CountableDefaultShopFactoryclass either has no constructor, or you have confused the name withDefaultShopFactory- Mikhail Vaysman