Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is an interesting problem. I'd like to reflect on the goal of this design, so you can correct me if I am mistaken. </p> <p>From your description, it seems like a Service can have multiple Rates. A Service instance relates to one (or more?) of the following instances:</p> <blockquote> <p>SeasonalRate, DiscountRate, ZipCodeRate, etc.</p> </blockquote> <p>I also gather that there is such a thing as a Visitor object, and it relates to one or more Services:</p> <blockquote> <p>DayService, NightService, TwentyFourService, etc.</p> </blockquote> <p><strong>I believe the task here is to correctly charge a Visitor, depending on the properties of the Service being performed, and the Rates that are applicable?</strong></p> <p>Visualizing the relationships should help you understand the interfaces that are necessary. It seems that all Rates must implement an interface that all Services can call.</p> <pre><code>public interface IRate { decimal GetRate(Service s); } </code></pre> <p>This allows Rates to decide, based on the Service, what the return value should be. Now it would be important that all Services implement the interfaces (IChargeable, IExtendable, etc.) so that all the data necessary to make a decision is available to every Rate object.</p> <p>Here's an example of what I am thinking:</p> <pre><code>public interface IThumbnail { string ThumbnailFile { get; } int ThumbnailSize { get; } Image GetThumbnail(); } public interface IThumbnailProvider { Image GetThumbnail(Service s); } public class Thumbnail : IThumbnailProvider { public Image GetThumbnail(Service s) { if(s.ThumbnailFile != null) { // get the image } } } public interface ISeasonal { SeasonType Season { get; } } public class SeasonalRate : IRate { public decimal GetRate(Service s) { if(s.Season != SeasonType.None) { // return seasonal rate based on s.Season } else { // throw an exception or do something else } } public abstract class Service : IChargeable, IExtendable, ISeasonal, IThumbnail { // default implementation for ISeasonal protected SeasonType _season = SeasonType.None; public SeasonType Season { get { return _season; } } // default implementation for IThumbnail protected string _thumbFile = null; protected int _thumbSize = 32; public string ThumbnailFile { get { return _thumbFile; } } public int ThumbnailSize { get { return _thumbnailSize; } } public Image GetThumbnail() { return null; // } } public class DayService : Service { private IRate _confirmedRate; private IThumbnailProvider _fileServer; public decimal GetRate() { return confirmedRate.GetRate(this); } public Image GetThumbnail() { return fileServer.GetThumbnail(); } // constructor public DayService(IThumbnailProvider fileServer, IRate confirmedRate) { this._season = SeasonType.Day; this._filename = "sunny.jpg"; this._fileServer = fileServer; this._confirmedRate = confirmedRate; } } </code></pre> <p>This lets your Rate objects change according to your needs, but reduces the changes necessary to each Service, since your business variables should be pretty well defined and relatively unchanging in the Service base class.</p> <p>For example, your NightService may not have a thumbnail, and so it would not need to implement the GetThumbnail function explicitly. It simply inherits the default implementation on Service.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload