C# Decorators - Interfaces or Abstract Classes? - c#

This thread, Decorator pattern implementation, has an implementation of a decorator using abstract classes. I don't like it for the simple fact that a CondimentDecorator is NOT a Beverage in the implementation given there. I'd use interfaces instead. Aren't abstract classes better for is-a relationships, and interfaces better for has-a relationships?
public interface IBeverage
{
// get a description of the beverage
String Description { get; }
// calculate cost of the beverage
double Cost { get; }
}
// HouseBlend coffee implements IBeverage
public class HouseBlend : IBeverage
{
private string description;
public String Description
{
get { return description; }
}
private double cost;
public double Cost
{
get { return cost; }
}
// Constructor
public HouseBlend() { description = "House Blend"; cost = 0.89; }
}
// DarkRoast coffee implements IBeverage
public class DarkRoast : IBeverage
{
private string description;
public String Description
{
get { return description; }
}
private double cost;
public double Cost
{
get { return cost; }
}
// Constructor
public DarkRoast() { description = "Dark Roast"; cost = 1.10; }
}
// Mocha is a Decorator
public class Mocha
{
// Mocha has-a Beverage
private IBeverage m_beverage;
private string description;
public String Description
{
get { return description; }
}
private public double Cost
{
get { return cost; }
}
// Constructor binds the object passed to member var
public Mocha(IBeverage beverage)
{
m_beverage = beverage; // not necessary for the purpose of this example
description = m_beverage.Description + ", Mocha";
cost = 0.20 + m_beverage.Cost;
}
}
Use like this:
Mocha mhb = new Mocha(new HouseBlend()); // house blend with mocha flavor

Both base clases and interfaces are frequently used to model is-a relationships. Even an interface as simple as IDisposable can be understood as "is an object with a manually controlled lifecycle", a "disposable". The more tangible differences are in whether base implementation or data fields are allowed; and in their ability to combine multiple hierarchies.
Now, when you are implementing any pattern, you usually have enough information to see whether you need data fields or not. However, you will hardly ever be able to rule out a future need to involve the same classes in additional patterns as your software grows. From that perspective, a general preference of interfaces over abstract classes gives you more long term flexibility - whenever you have a choice.
By the nature of a Decorator, you have a choice. The components typically do not have a predefined order of how they should nest. If they did, you would use inheritance directly, instead of components. So you should prefer interfaces to compose a Decorator.
All that said, your original argument is valid as well. Decorator components (features) can be understood as is-a relationships if you like; but it is not the most natural way of looking at them.

Related

is it posible to relate two different classes that contains same method but with different parameters?

I'm defining an Interface to group two different subclasses. Each class implements the inherit method but each needs different parameters to be able to work.
Here's the interface.
public interface Billable()
{
decimal Bill();
}
Here's the first class
public class HourlyEmployee : Billable
{
public decimal Bill(int hoursWorked, decimal pricePerHour) { }
}
Here's the second
public class CommissionEmployee : Billable
{
public decimal Bill(decimal commisionPercentage) { }
}
As you can see, conceptually they use the method to achieve the same, which is charging for a service. That's why I initially thought about inheritance, but it seems that's not the best approach.
What other alternatives can make the classes relate to each other?
This doesn't directly answer the question in your title, but you did ask for other alternatives...
Your interface is a contract, guaranteeing that your classes will have a Bill() function that returns a decimal. But that doesn't mean you have to accept the parameters in that method.
Here the constructors for each class accept the parameters. The Bill() method does the calculation to return the appropriate value.
public interface IBillable
{
decimal Bill();
}
public class HourlyEmployee : IBillable
{
private int hoursWorked;
private decimal pricePerHour;
public HourlyEmployee(int hoursWorked, decimal pricePerHour)
{
this.hoursWorked = hoursWorked;
this.pricePerHour = pricePerHour;
}
public decimal Bill()
{
return hoursWorked * pricePerHour;
}
}
public class CommissionEmployee : IBillable
{
private int commissionPercentage;
public CommissionEmployee(int commissionPercentage)
{
this.commissionPercentage = commissionPercentage;
}
public decimal Bill()
{
// do some calculation using commissionPercentage and return a value...
}
}
Not sure if this is the best approach, but I think your approach of using an interface is good (which I'd call IBillable by convention).
But you should not try to accommodate all the required values for the calculation as parameters in the interface method, as this limits your extensibility, what if you come across a new kind of employee who needs one more value for bill calculation. Interface is a contract which should not change, hopefully ever. Method suggested below doesn't have that problem.
One suggestion is to use another class (let's say BillCalculator) and move the different parameters required by the Billable interface to properties of that class.
public abstract class BillCalculator: IBillable
{
abstract decimal Bill();
}
public class HourlyBillCalculator: BillCalculator
{
public int HoursWorked { get; set; }
public decimal PricePerHour { get; set; }
public HourlyBillCalculator(int hoursWorked, decimal pricePerHour)
{
HoursWorked = hoursWorked;
PricePerHour = pricePerHour;
}
public override Bill()
{
// Calculate the Bill
}
}
public class CommisionBillCalculator: BillCalculator {
public decimal CommisionRate { get; set; }
public CommisionBillCalculator(decimal rate)
{
CommisionRate = rate;
}
public override Bill() {
// Calculate the Bill
}
}
Corresponding Calculator class has to be instantiated using a factory pattern or something to fit the need. Then it's just a matter of calling the Bill method, which will use the instance properties to calculate the value.
That will let you keep interface signature consistent.
Note: Syntax may be off, but hope you get the idea.
Obviously what you propose produces a syntax error as every implementation of the interface should implement all its prototyped methods. By definition, implementing a prototype means having the same parameters, that's why you cannot have multiple parameters for the same method. However, you can take the advantage of the optional parameters introduced in .NET 4.0
So you can have something like this.

creating decorators. design patterns

let's say two simple decorators are defined:
// decorated object
class Product : IComponent {
// properties..
// IComponent implementation
public Decimal GetCost() {
return this.SelectedQuantity * this.PricePerPiece;
}
}
// decorators
class FixedDiscountDecorator : IComponent {
IComponent component;
// IComponent implemantation
public Decimal GetCost() {
// ...
}
public FixedDiscountDecorator(IComponent product, Decimal discountPercentage) {
// ...
}
}
class BuyXGetYFreeDiscountDecorator : IComponent {
IComponent component;
// IComponent implemantation
public Decimal GetCost() {
// ...
}
// X - things to buy
// Y - things you get free
public BuyXGetYFreeDiscountDecorator(IComponent product, Int32 X, Int32 Y) {
// ...
}
}
These decorators have different constructors' signature (parameter list). I was looking for a pattern to apply to construct decorators like it could be with factory pattern. I mean I put a string and get a decorator instance.
As a result I want to simply apply a chain of decorators to a given product:
var product = new SimpleProduct {
Id = Guid.NewGuid(),
PricePerPiece = 10M,
SelectedQuantity = 10,
Title = "simple product"
};
var itemsToApplyTheDiscount = 5;
var itemsYouGetFree = 2;
var discountPercentage = 0.3M;
var discountA = new BuyXGetYFreeDecorator(product, itemsToApplyTheDiscount, itemsYouGetFree);
var discountB = new FixedDiscountDecorator(discountA, discountPercentage);
This can be resolved using IOC container or something similar. Some of the containers popped up in my head is Unity, Windsor and SimpleInjector. I will leave the IOC container to other answers since I have no experience there.
However, I really wonder why you inject a native value.
Seeing about how the class will be used, it feels weird to have an injected value like discount percentage or x buy y free item injected into the constructor.
What if the user put 10 (as percent) instead of 0.1 (as decimal) as the discount parameter? It makes ambiguity. Additionaly, if you add checks at the constructor, you give another responsibility to the class, violating SRP.
I suggest to add a DTO such as DiscountPercentValue or BuyXGetYFreeValue. Moreover, I prefer the value of discount is being set as a context or there is a repository to be injected for it. Otherwise, someday you will need factories to handle if-else business rules related to discounts.
EDIT1:
Usually I keep the constructor validation as null checks only. Other validation than that can be considered violation.
As for the repository things, I imagine some interfaces like these:
public interface IDiscountPercentageProvider{
DiscountValue Get();
}
public interface IBuyXGetYFreeValueProvider{
BuyXGetYFreeValue Get();
}
Then in your service class, you can use something like this:
class FixedDiscountDecorator : IComponent {
IComponent component;
// IComponent implemantation
IDiscountPercentageProvider discountPercentageProvider;
public Decimal GetCost() {
DiscountValue discount = discountPercentageProvider.Get();
// ...
}
public FixedDiscountDecorator(IComponent product
, IDiscountPercentageProvider discountPercentageProvider) {
// ... just null checks here
}
}
This may be complicated at first. However, it provides better API design (no ambiguity now when using decorator). Using this, you can create a DiscountValue as a class that protects its invariants, making it safer to be used in other classes.
In your example you do show a chain of decorators applied to a given product, namely:
var discountA = new BuyXGetYFreeDecorator(product, itemsToApplyTheDiscount, itemsYouGetFree);
var discountB = new FixedDiscountDecorator(discountA, discountPercentage);
Is the question, then, what are some patterns that could be used to change the state of product governed by a specified property, building from your code above? Using your example you have and limiting my scope to determining the product Cost:
public interface IComponent
{
decimal GetCost { get; set; }
}
I would create a product class representing IComponent
public class Product
{
public IComponent Price { get; set; }
}
You may have a "default" implementation in addition to the decorator classes
public class BasePrice : IComponent
{
private Decimal _cost;
public decimal GetCost //as a property maybe use Cost with get; set; in IComponent
{
get { return _cost; }
set { _cost = value; }
}
}
I like your two decorator classes which use IoC and implement variations of cost (GetCost()) from IComponent.
To this point I have not really added anything, only a base price class. What I might do next is use an abstract class and defer specific operations to subclasses, as represented in the Template Method pattern. My concrete classes would inherit from this base class. The concrete class created will depend upon the action type passed into Factory method pattern, the class referred to below as WarrantyProcessFactory.
You mentioned using app.config ... I like enums which I would use to specify the action types to be applied to product. So let's say I want to have actions tied to the product's warranty so I can process products based on this.
public enum WarrantyAction
{
RefundProduct = 0,
ReplaceProduct = 1
}
I will use a warranty request class to represent compensation requests by customers for defective products
public class WarrantyRequest
{
public WarrantyAction Action { get; set; }
public string PaymentTransactionId { get; set; }
public decimal PricePaid { get; set; }
public decimal PostageCost { get; set; }
public long ProductId { get; set; }
public decimal AmountToRefund { get; set; }
}
Finally, I could implement the abstract template method that will be overridden by concrete classes representative of the warranty action enums
public abstract class WarrantyProcessTemplate
{
protected abstract void GenerateWarrantyTransactionFor(WarrantyRequest warrantyRequest);
protected abstract void CalculateRefundFor(WarrantyRequest warrantyRequest);
public void Process(WarrantyRequest warrantyRequest)
{
GenerateWarrantyTransactionFor(warrantyRequest);
CalculateRefundFor(warrantyRequest);
}
}
The class and the first two methods are abstract and are required to be implemented by a subclass. The third method simply calls in the two abstract methods and passes a WarrantyRequest entity as an argument.
Cases in which the client wants a refund
public class RefundWarrantyProcess : WarrantyProcessTemplate
{
protected override void GenerateWarrantyTransactionFor(WarrantyRequest warrantyRequest)
{
// Code to determine terms of the warranty and devalutionAmt...
}
protected override void CalculateRefundFor(WarrantyRequest warrantyRequest)
{
WarrantyRequest.AmountToRefund = warrantyRequest.PricePaid * devalutionAmt;
}
}
Cases in which the client wants a replacement product
public class ReplaceWarrantyProcess : WarrantyProcessTemplate
{
protected override void GenerateWarrantyTransactionFor(WarrantyRequest warrantyRequest)
{
// Code to generate replacement order
}
protected override void CalculateRefundFor(WarrantyRequest warrantyRequest)
{
WarrantyRequest.AmountToRefund = warrantyRequest.PostageCost;
}
}
public static class WarrantyProcessFactory
{
public static WarrantyProcessTemplate CreateFrom(WarrantyAction warrantyAction)
{
switch (warrantyAction)
{
case (WarrantyAction.RefundProduct):
return new RefundWarrantyProcess();
case (WarrantyAction.ReplaceProduct):
return new ReplaceWarrantyProcess();
default:
throw new ApplicationException(
"No Process Template defined for Warranty Action of " +
warrantyAction.ToString());
}
}
}
Another pattern I would consider is the Strategy Method pattern. In this case a Context class defers all calculations to a "ConcreteStrategy" referenced by its abstract class or interface. I found Scott Millet's book "Professional ASP.NET Design Patterns" as a useful resource and often return to it.
I am open to comments and criticism.

How to represent different entities that have identical behavior?

I have several different entities in my domain model (animal species, let's say), which have a few properties each. The entities are readonly (they do not change state during the application lifetime) and they have identical behavior (the differ only by the values of properties).
How to implement such entities in code?
Unsuccessful attempts:
Enums
I tried an enum like this:
enum Animals {
Frog,
Duck,
Otter,
Fish
}
And other pieces of code would switch on the enum. However, this leads to ugly switching code, scattering the logic around and problems with comboboxes. There's no pretty way to list all possible Animals. Serialization works great though.
Subclasses
I also thought about where each animal type is a subclass of a common base abstract class. The implementation of Swim() is the same for all Animals, though, so it makes little sense and serializability is a big issue now. Since we represent an animal type (species, if you will), there should be one instance of the subclass per application, which is hard and weird to maintain when we use serialization.
public abstract class AnimalBase {
string Name { get; set; } // user-readable
double Weight { get; set; }
Habitat Habitat { get; set; }
public void Swim(); { /* swim implementation; the same for all animals but depends uses the value of Weight */ }
}
public class Otter: AnimalBase{
public Otter() {
Name = "Otter";
Weight = 10;
Habitat = "North America";
}
}
// ... and so on
Just plain awful.
Static fields
This blog post gave me and idea for a solution where each option is a statically defined field inside the type, like this:
public class Animal {
public static readonly Animal Otter =
new Animal
{ Name="Otter", Weight = 10, Habitat = "North America"}
// the rest of the animals...
public string Name { get; set; } // user-readable
public double Weight { get; set; }
public Habitat Habitat { get; set; }
public void Swim();
}
That would be great: you can use it like enums (AnimalType = Animal.Otter), you can easily add a static list of all defined animals, you have a sensible place where to implement Swim(). Immutability can be achieved by making property setters protected. There is a major problem, though: it breaks serializability. A serialized Animal would have to save all its properties and upon deserialization it would create a new instance of Animal, which is something I'd like to avoid.
Is there an easy way to make the third attempt work? Any more suggestions for implementing such a model?
If you have issues with serialization, you can always separate the application-code from the serialization code. That is, place conversion classes that convert to/from your serialized state. The serialized instances can have exposed any empty constructors and properties needed and their only job is to serialize state. Meanwhile, your application logic works with the non-serializable, immutable objects. This way you do not mix your serialization concerns with logical concerns which brings with it a host of disadvantages as you are finding out.
EDIT: Here's some example code:
public class Animal
{
public string Name { get; private set; }
public double Weight { get; private set; }
public Habitat Habitat { get; private set; }
internal Animal(string name, double weight, Habitat habitat)
{
this.Name = name;
this.Weight = weight;
this.Habitat = habitat;
}
public void Swim();
}
public class SerializableAnimal
{
public string Name { get; set; }
public double Weight { get; set; }
public SerializableHabitat Habitat { get; set; } //assuming the "Habitat" class is also immutable
}
public static class AnimalSerializer
{
public static SerializableAnimal CreateSerializable(Animal animal)
{
return new SerializableAnimal {Name=animal.Name, Weight=animal.Weight, Habitat=HabitatSerializer.CreateSerializable(animal.Habitat)};
}
public static Animal CreateFromSerialized(SerializableAnimal serialized)
{
return new Animal(serialized.Name, serialized.Weight, HabitatSerializer.CreateFromSerialized(serialized.Habitat));
}
//or if you're using your "Static fields" design, you can switch/case on the name
public static Animal CreateFromSerialized(SerializableAnimal serialized)
{
switch (serialized.Name)
{
case "Otter" :
return Animal.Otter
}
return null; //or throw exception
}
}
Then your application logic for serialization might look something like:
Animal myAnimal = new Animal("Otter", 10, "North America");
Animal myOtherAnimal = Animal.Duck; //static fields example
SerializableAnimal serializable = AnimalSerializer.CreateSerializable(myAnimal);
string xml = XmlSerialize(serializable);
SerializableAnimal deserialized = XmlDeserializer<SerializableAnimal>(xml);
Animal myAnimal = AnimalSerializer.CreateFromSerialized(deserialized);
Just to reiterate, the SerializableAnimal class and usage is ONLY used in the final layer(s) of your application that need to serialize/deserialize. Everything else works against your immutable Animal classes.
EDITx2: Another major benefit of this managed separation is you can deal with legacy changes in your code. For example, you have a Fish type, which is pretty broad. Maybe you split it into Shark and Goldfish later and decide all your old Fish type should be considered Goldfish. With this separation of serialization, you can now place a check for any old Fish and convert them to Goldfish whereas direct serialization would result in an exception because Fish no longer exists.
I would implement it with subclasses, but where the instances of the subclasses don't store any data, like this:
public abstract class AnimalBase {
public abstract string Name { get; } // user-readable
public abstract double Weight { get; }
public abstract Habitat Habitat { get; }
public void Swim(); { /* swim implementation; the same for all animals but uses the value of Weight */ }
// ensure that two instances of the same type are equal
public override bool Equals(object o)
{
return o != null && o.GetType() == this.GetType();
}
public override int GetHashCode()
{
return this.GetType().GetHashCode();
}
}
// subclasses store no data; they differ only in what their properties return
public class Otter : AnimalBase
{
public override string Name { return "Otter"; }
public override double Weight { return 10; }
// here we use a private static member to hold an instance of a class
// that we only want to create once
private static readonly Habitat habitat = new Habitat("North America");
public override Habitat Habitat { return habitat; }
}
Now it shouldn't matter that you have multiple "instances", because each instance only contains its type information (no actual data). Overriding Equals and GetHashCode on the base class means that different instances of the same class will be considered equal.
The way I see it, you are looking for the right creational pattern to suit your needs.
Your first option is similar to factory method.
The second one looks like a type hierarchy with an optional abstract factory.
The third one is a singleton.
It seems like your only problem is serialization. What kind of serialization we're talking about: binary or XML? If it's binary, have you looked at custom serialization? If it's XML, you should either stick with the second option, also use custom serialization or delegate the serialization logic outside of your classes.
I personally think the latter is the most architecturally sound solution. Mixing object creation and serialization is a bad idea.
I'd go with the third option (objects!), but with a little twist.
The point is: You have a set of objects with some particular schema...
public class Animal {
public string Name { get; set; } // user-readable
public double Weight { get; set; }
public Habitat Habitat { get; set; }
public void Swim();
}
but you want them to be predefined. The catch is: If you serialize such object, you don't want to have its fields serialized. Initializing the fields is the responsibility of application, and the only thing you want to actually have in your serialized version is the "type" of the animal. This will allow you to change "Otter" to "Sea Otter" and keep the data consistent.
Hence, you'd need some representation of the "animal type" - and that's the only thing you want to have serialized. On deserialization, you want to read the type identifier and initialize all the fields based on it.
Oh, and another catch - upon deserialization, you don't want to create a new object! You want to read the ID (and the ID only) and retrieve one of the predefined objects (that corresponds to this ID).
The code could look like:
public class Animal {
public static Animal Otter;
public static Animal Narwhal;
// returns one of the static objects
public static Animal GetAnimalById(int id) {...}
// this is here only for serialization,
// also it's the only thing that needs to be serialized
public int ID { get; set; }
public string Name { get; set; }
public double Weight { get; set; }
public Habitat Habitat { get; set; }
public void Swim();
}
So far, so good. If there are dependencies that prohibit you from making instances static, you could throw in some lazy initialization for all the Animal objects.
The Animal class starts to kind of look like "a couple singletons in one place".
Now how to hook it into .NET's serialization mechanism (BinarySerializer or DataContractSerializer). We want the serializer to use GetAnimalById instead of the constructor when deserializing, and only store ID when serializing.
Depending on your serialization API, you can do this with ISerializationSurrogate or IDataContractSurrogate. This is an example:
class Surrogate : IDataContractSurrogate {
public Type GetDataContractType(Type type) {
if (typeof(Animal).IsAssignableFrom(type)) return typeof(int);
return type;
}
public object GetObjectToSerialize(object obj, Type targetType) {
// map any animal to its ID
if (obj is Animal) return ((Animal)obj).ID;
return obj;
}
public object GetDeserializedObject(object obj, Type targetType) {
// use the static accessor instead of a constructor!
if (targetType == typeof(Animal)) return Animal.GetAnimalById((int)obj);
}
}
BTW: DataContacts seem to have a bug (or is it a feature?) which causes them to act weirdly when the substitute type is a basic type. I've had such problem when serializing objeects as strings - the GetDeserializedObject method was never fired when deserializing them. If you run into this behaviour, use a wrapper class or struct around that single int field in the surrogate.

Inheritance problem in C#

I'm refactoring some code and want to classes a bit higher in the inheritance chain be a bit more strict with their parameters. As I'm not sure I'm explaining this correctly, here's what I've got:
public interface ISvdPredictor
{
List<string> Users { get; set; }
List<string> Artists { get; set; }
float PredictRating(ISvdModel model, string user, string artist);
float PredictRating(ISvdModel model, int userIndex, int artistIndex);
}
ISvdPredictor uses ISvdModel:
public interface ISvdModel
{
float[,] UserFeatures { get; set; }
float[,] ArtistFeatures { get; set; }
}
Now I want to implement another variation:
public interface IBiasSvdPredictor : ISvdPredictor
{
float PredictRating(IBiasSvdModel model, string user, string artist);
float PredictRating(IBiasSvdModel model, int userIndex, int artistIndex);
}
Which uses IBiasSvdModel which derives from ISvdModel:
public interface IBiasSvdModel : ISvdModel
{
float GlobalAverage { get; set; }
float[] UserBias { get; set; }
float[] ArtistBias { get; set; }
}
IBiasSvdPredictor will not work with ISvdModel.
The problem is that when I implement IBiasSvdPredictor I'd have to implement 2 pairs of PredictRating methods. One from ISvdPredictor and the other from IBiasSvdPredictor. What do I need to do to be able to just implement those from IBiasSvdPredictor?
I've tried generics as well, but couldn't restrict the PredictRating for BiasSvdPredictor to IBiasSvdModel using the where directive. I may be doing this all wrong so any suggestion might help. I think you get what I'm trying to do.
EDIT: If anyone needs more context see https://github.com/gligoran/RecommendationSystem. I'm writing this code for my thesis for BSc.
You could use generics and constraints.
public interface ISvdModel
{
float[,] UserFeatures { get; set; }
float[,] ArtistFeatures { get; set; }
}
public interface IBiasSvdModel : ISvdModel
{
float GlobalAverage { get; set; }
float[] UserBias { get; set; }
float[] ArtistBias { get; set; }
}
public interface ISvdPredictor<in TSvdModel>
where TSvdModel : ISvdModel // Require that TSvdModel implements ISvdModel
{
List<string> Users { get; set; }
List<string> Artists { get; set; }
float PredictRating(TSvdModel model, string user, string artist);
float PredictRating(TSvdModel model, int userIndex, int artistIndex);
}
// I would actually avoid declaring this interface. Rather, see comment on the class.
public interface IBiasSvdPredictor : ISvdPredictor<IBiasSvdModel> { }
class BiasSvdPredictor : IBiasSvdPredictor // Preferred : ISvdPredictor<IBiasSvdModel>
{
// ...
public float PredictRating(IBiasSvdModel model, string user, string artist) { }
public float PredictRating(IBiasSvdModel model, int userIndex, int artistIndex) { }
}
The interface should have one method, PredictRating. I wouldn't have two interfaces that have the same method to implement. Confusing.
Create an abstract class that implements your interface. Make PredictRating a virtual method so inheritors can override as they see fit. You could even do a default implementation on the abstract class.
One interface, One abstract class. N concrete class that implement PredictRating as they see fit.
public interface Demo
{
int PredictRating(int param1);
}
public abstract class AbstractDemo : Demo
{
public virtual int PredictRating(int param1)
{
return param1 + 1;
}
}
public class ClassDemo1 : AbstractDemo
{
//This guy uses AbstractDemo Predict Rating
public override int PredictRating(int param1)
{
return base.PredictRating(param1);
}
}
public class ClassDemo2 : AbstractDemo
{
//This guy overrides the predict rating behavior
public override int PredictRating(int param1)
{
return param1 + 2;
}
}
You have to implement all four methods. They have different signatures and thus are considered to be different. However, you can have one delegate to the other, and sometimes using explicit implementation helps with that.
public class Foo : IBiasSvdPredictor {
public float PredictRating(IBiasSvdModel, string user, string artist) { .... }
// this is an expicit implementation of ISvdPredictor's method. You satisfy
// the interface, but this method is not a public part of the class. You have to
// cast the object to ISvdPredictor in order to use this method.
float ISvdPredictor.PredictRating(ISvdModel model, string user, string artist) {
this.PredictRating((IBiasSvdModel)model, user, artist);
}
}
This of course will not work if the ISvdModel is not actually an IBiasSvdModel.
You can use explicit interface implementation to hide the ones from ISvdPredictor, but you should implement them all or have a base abstract class to handle them.
I'd have to implement 2 pairs of PredictRating methods.
Of course you do. What did you expect?
If your IBiasSvdPredictor must take a IBiasSvdModel in its PredictRating method, than IBiasSvdPredictor is not an ISvdPredictor (because it cannot take a ISvdModel as the first parameter to PredictRating) and inheriting IBiasSvdPredictor from ISvdPredictor is the wrong choice.
In my opinion, you should simply keep the interfaces separate and not inherit one from the other.
Without having a full understanding of your object model (so this may not actually apply in your situation), it seems like maybe ISvdModel shouldn't be part of the interface definition. It seems more like it's an implementation detail, not necessarily part of the contract you're trying to enforce. To me it makes more sense to pass ISvdModel (or IBiasSvdModel) into the constructor of your implementation class, not have it as part of your ISvdPredictor interface. Then you wouldn't need 2 separate interface definitions at all, you would just have 2 implementations of the single interface.
You might even be able to take it one step further; if the only difference between ISvdPredictor and IBiasSvdPredictor is that one uses a ISvdModel and the other uses a IBiasSvdModel, you wouldn't even need 2 implementations, just one, and you would pass in the correct instance of ISvdModel for each situation. This is a design pattern called Inversion of Control, specifically using Dependency Injection, and is very powerful to achieve higher levels of code reuse in your programs.

Creating read-only versions of classes in a complex object structure

In my current project I need to be able to have both editable and read-only versions of classes. So that when the classes are displayed in a List or PropertGrid the user is not able to edit objects they should not be allowed to.
To do this I'm following the design pattern shown in the diagram below. I start with a read-only interface (IWidget), and then create an edtiable class which implements this interface (Widget). Next I create a read-only class (ReadOnlyWidget) which simply wraps the mutable class and also implements the read only interface.
I'm following this pattern for a number of different unrelated types. But now I want to add a search function to my program, which can generate results that include any variety of types including both mutable and immutable versions. So now I want to add another set of interfaces (IItem, IMutableItem) that define properties which apply to all types. So IItem defines a set of generic immutable properties, and IMutableItem defines the same properties but editable. In the end a search will return a collection of IItems, which can then later be cast to more specific types if needed.
Yet, I'm not sure if I'm setting up the relationships to IMutable and IItem correctly. Right now I have each of the interfaces (IWidget, IDooHickey) inheriting from IItem, and then the mutable classes (Widget, DooHickey) in addition also implement IMutableItem.
Alternatively, I was also thinking I could then set IMutableItem to inherit from IItem, which would hide its read-only properties with new properties that have both get and set accessors. Then the mutable classes would implement IMutableItem, and the read-only classes would implement IItem.
I'd appreciate any suggestions or criticisms regarding any of this.
Class Diagram
Code
public interface IItem
{
string ItemName { get; }
}
public interface IMutableItem
{
string ItemName { get; set; }
}
public interface IWidget:IItem
{
void Wiggle();
}
public abstract class Widget : IWidget, IMutableItem
{
public string ItemName
{
get;
set;
}
public void Wiggle()
{
//wiggle a little
}
}
public class ReadOnlyWidget : IWidget
{
private Widget _widget;
public ReadOnlyWidget(Widget widget)
{
this._widget = widget;
}
public void Wiggle()
{
_widget.Wiggle();
}
public string ItemName
{
get {return _widget.ItemName; }
}
}
public interface IDoohickey:IItem
{
void DoSomthing();
}
public abstract class Doohickey : IDoohickey, IMutableItem
{
public void DoSomthing()
{
//work it, work it
}
public string ItemName
{
get;
set;
}
}
public class ReadOnlyDoohickey : IDoohickey
{
private Doohickey _doohicky;
public ReadOnlyDoohickey(Doohickey doohicky)
{
this._doohicky = doohicky;
}
public string ItemName
{
get { return _doohicky.ItemName; }
}
public void DoSomthing()
{
this._doohicky.DoSomthing();
}
}
Is it OK to create another object when you need a readonly copy? If so then you can use the technique in the included code. If not, I think a wrapper is probably your best bet when it comes to this.
internal class Test
{
private int _id;
public virtual int ID
{
get
{
return _id;
}
set
{
if (ReadOnly)
{
throw new InvalidOperationException("Cannot set properties on a readonly instance.");
}
}
}
private string _name;
public virtual string Name
{
get
{
return _name;
}
set
{
if (ReadOnly)
{
throw new InvalidOperationException("Cannot set properties on a readonly instance.");
}
}
}
public bool ReadOnly { get; private set; }
public Test(int id = -1, string name = null)
: this(id, name, false)
{ }
private Test(int id, string name, bool readOnly)
{
ID = id;
Name = name;
ReadOnly = readOnly;
}
public Test AsReadOnly()
{
return new Test(ID, Name, true);
}
}
I would suggest that for each main class or interface, there be three defined classes: a "readable" class, a "changeable" class, and an "immutable" class. Only the "changeable" or "immutable" classes should exist as concrete types; they should both derive from an abstract "readable" class. Code which wants to store an object secure in the knowledge that it never changes should store the "immutable" class; code that wants to edit an object should use the "changeable" class. Code which isn't going to write to something but doesn't care if it holds the same value forever can accept objects of the "readable" base type.
The readable version should include public abstract methods AsChangeable(), AsImmutable(), public virtual method AsNewChangeable(), and protected virtual method AsNewImmutable(). The "changeable" classes should define AsChangeable() to return this, and AsImmutable to return AsNewImmutable(). The "immutable" classes should define AsChangeable() to return AsNewChangeable() and AsImmutable() to return this.
The biggest difficulty with all this is that inheritance doesn't work terribly well if one tries to use class types rather than interfaces. For example, if one would like to have an EnhancedCustomer class which inherits from BasicCustomer, then ImmutableEnhancedCustomer should inherit from both ImmutableBasicCustomer and ReadableEnhancedCustomer, but .net doesn't allow such dual inheritance. One could use an interface IImmutableEnhancedCustomer rather than a class, but some people would consider an 'immutable interace' to be a bit of a smell since there's no way a module that defines an interface in such a way that outsiders can use it without also allowing outsiders to define their own implementations.
Abandon hope all ye who enter here!!!
I suspect that in the long run your code is going to be very confusing. Your class diagram suggests that all properties are editable (or not) in a given object. Or are your (I'm)mutable interfaces introducing new properties that are all immutable or not, separate from the "core"/inheriting class?
Either way I think you're going to end up with playing games with property name variations and/or hiding inherited properties
Marker Interfaces Perhaps?
Consider making all properties in your classes mutable. Then implement IMutable (I don't like the name IItem) and IImutable as a marker interfaces. That is, there is literally nothing defined in the interface body. But it allows client code to handle the objects as a IImutable reference, for example.
This implies that either (a) your client code plays nice and respects it's mutability, or (b) all your objects are wrapped by a "controller" class that enforces the given object's mutability.
Could be too late :-), but the cause "The keyword 'new' is required on property because it hides property ..." is a bug in Resharper, no problem with the compiler. See the example below:
public interface IEntityReadOnly
{
int Prop { get; }
}
public interface IEntity : IEntityReadOnly
{
int Prop { set; }
}
public class Entity : IEntity
{
public int Prop { get; set; }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var entity = new Entity();
(entity as IEntity).Prop = 2;
Assert.AreEqual(2, (entity as IEntityReadOnly).Prop);
}
}
Same for the case without interfaces. The only limitation, you can't use auto-properties
public class User
{
public User(string userName)
{
this.userName = userName;
}
protected string userName;
public string UserName { get { return userName; } }
}
public class UserUpdatable : User
{
public UserUpdatable()
: base(null)
{
}
public string UserName { set { userName = value; } }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var user = new UserUpdatable {UserName = "George"};
Assert.AreEqual("George", (user as User).UserName);
}
}

Categories