Decorator pattern for a Customer class - c#

Suppose I have a Customer class. A customer can have multiple kinds of loyalty points. For one promotion, the customer may be collecting Rewards. In another, the customer may be collecting Miles. And there is no fixed number of kinds of loyalty points that the Customer is built for. I am sure this is a common use case. Is the decorator pattern a good fit given below sample code?
public interface ICustomer
{
void Display();
}
public class SimpleCustomer : ICustomer
{
public void Display()
{
Console.WriteLine("I am simple customer");
}
}
public abstract class CustomerDecorator : ICustomer
{
protected ICustomer customer;
public CustomerDecorator(ICustomer customer)
{
this.customer = customer ?? throw new ArgumentNullException("customer");
}
public abstract void Display();
}
public class RewardsDecorator : CustomerDecorator
{
private int rewards;
public RewardsDecorator(ICustomer customer, int rewards) : base(customer)
{
this.rewards = rewards;
}
public override void Display()
{
Console.WriteLine("Now I have " + rewards.ToString() + " rewards");
}
}
public class MilesDecorator : CustomerDecorator
{
private int miles;
public MilesDecorator(ICustomer customer, int miles) : base(customer)
{
this.miles = miles;
}
public override void Display()
{
Console.WriteLine("Now I have " + miles.ToString() + " miles");
}
}

Don't think Decorator pattern does what you want it to do. Decorator adds new functionalities on top of the original class. A typical wiki example would say, we can add scroll bar, menu bar, overlays and other UI components on top of canvas. So to make a proper browser window, so you will have:
public class Canvas
public class ScrollableCanvas
public class OverlayedCanvas
etc.
So that we add more functionalities to the original Canvas.
To solve your problem, you should have something like:
public abstract class LoyaltyProgramAccount {...}
public class RewardAccount extends LoyaltyProgramAccount {...}
public class MilesAccount extends LoyaltyProgramAccount {...}
And then add a registery-ish enum:
public enum LoyaltyProgramTypes {
miles,
reward,
}
and then let user be:
public class Customer {
private List<LoyaltyProgramTypes, LoyaltyProgramAccount> accounts;
public void openAccount(LoyaltyProgramTypes type, LoyaltyProgramAccount account) {
accounts.put(type, account);
}
...
}

I do not think that Decorator is the pattern you are looking for.
Besides, your code does not seem to be an implementation of the Decorator pattern. You do not add any functionality to the only function. You just override it. But adding to the existing function is what the Decorator pattern is all about.
My approach would be state / strategy pattern. There are different kinds of rewards. And a customer has one or more of them. These rewards may share a common interface and provide different implementations. The customer (or a subclass or compound object RewardedCustomer) should hold a list or map of these rewards.

I would use the visitor pattern, this is pretty ideal for your situation. This will allow you nicely separate the rewards calculations for you different customer types and run operations against all supported rewards types.
class Program
{
static void Main(string[] args)
{
MilesCustomer customer = new MilesCustomer();
ICustomerVisitor<int> visitor = new MilesCalculation(10);
var miles = customer.Visit(visitor);
visitor = new RewardsCalucation(100);
var rewards = customer.Visit(visitor);
}
}
public interface ICustomerVisitor<T>
{
T Visit(SimpleCustomer cusomter);
T Visit(RewardsCustomer cusomter);
T Visit(MilesCustomer cusomter);
}
public abstract class Customer
{
public Customer()
{
TotalMoneySpent = 10;
}
public int TotalMoneySpent { get; private set; }
public abstract T Visit<T>(ICustomerVisitor<T> visitor);
public virtual void Display()
{
Console.WriteLine("I am simple customer");
}
}
public class RewardsCalucation : ICustomerVisitor<int>
{
private int _rewardsPerDollar;
public RewardsCalucation(int rewardsPerDollar) => _rewardsPerDollar = rewardsPerDollar;
public int Visit(SimpleCustomer cusomter)
{
return 0;
}
public int Visit(RewardsCustomer cusomter)
{
return cusomter.TotalMoneySpent * _rewardsPerDollar;
}
public int Visit(MilesCustomer cusomter)
{
return 0;
}
}
public class MilesCalculation : ICustomerVisitor<int>
{
private int _milesPerDollar;
public MilesCalculation(int milesPerDollar) => _milesPerDollar = milesPerDollar;
public int Visit(SimpleCustomer cusomter)
{
return 0;
}
public int Visit(RewardsCustomer cusomter)
{
return 0;
}
public int Visit(MilesCustomer cusomter)
{
return cusomter.TotalMoneySpent * _milesPerDollar;
}
}
public class SimpleCustomer : Customer
{
public override T Visit<T>(ICustomerVisitor<T> visitor)
{
return visitor.Visit(this);
}
}
public class RewardsCustomer : Customer
{
public override T Visit<T>(ICustomerVisitor<T> visitor)
{
return visitor.Visit(this);
}
}
public class MilesCustomer : Customer
{
public override T Visit<T>(ICustomerVisitor<T> visitor)
{
return visitor.Visit(this);
}
}

Related

How can I solve this Interface Segregation Principle Violation

I'm facing a similar scenario to this issue and I was wondering if it's possible to get around a cleaner solution.
Supposing we have a party that has People on it, We have the interface:
public interface IPerson {
void Arrive();
void Dance();
}
And its implementations, people that are able to dance
public class PersonThatCanDance : IPerson {
public void Arrive() {
//Logic related to arriving
}
public void Dance() {
//Logic related to dancing
}
}
and those who aren't
public class PersonThatCannotDance : IPerson {
public void Arrive() {
//Logic related to arriving
}
public void Dance() {
}
}
Knowing this, now we have the party with 2 people
public class Party {
private IPerson person1;
private IPerson person2
private void StartParty() {
person1.Arrive();
person2.Arrive();
}
private void StartMusic() {
person1.Dance();
person2.Dance();
}
}
With this scenario settled, the problem comes when we want to make the party not care if the person is a person that can dance or not. The party throws the people into dancing no matter if they have functionality to do so.
From what I understand, the existence of the Dance() method in PersonThatCannotDance is a violation of ISP but making the party not care about what kind of person is preventing me from respecting the principle.
Is there a way to get around this? Thank you.
yes you are right. it is violation of ISP.
public interface IArrive : IPerson {
void Arrive();
DateTime Time {get;set;}
string Mode {get;set;}
}
public interface IDance: IPerson {
void Dance();
DateTime duration {get;set;}
string Type {get;set;}
}
public interface IPerson {
string Name {get;set;}
void Dress();
}
Now Implementations looks like this, people that are able to dance
public class PersonThatCanDance : IArrive,IDance {
string Name {get; set;}
public void Dress() {
//Logic related to arriving
}
public void Arrive() {
//Logic related to arriving
}
public void Dance() {
//Logic related to dancing
}
}
and those who aren't
public class PersonThatCannotDance : IArrive {
string Name {get; set;}
public void Dress() {
//Logic related to arriving
}
public void Arrive() {
//Logic related to arriving
}
}
In Party Class
public class Party {
private IPerson person1 = new PersonThatCanDance();
private IPerson person2 = new PersonThatCannotDance();
private void StartParty() {
((IArrive)person1).Arrive();
((IArrive)person2).Arrive();
}
private void StartMusic() {
if(person1 is IDance)
{
((IDance)person1).Dance();
}
if(person2 is IDance)
{
((IDance)person2).Dance();
}
}
}
Now I hope this solution will work. please let me know if still have doubt.
There is not enough information to determine the right design for your situation, but I can offer a design that's broadly applicable:
public interface IPerson {
void Arrive();
}
public class PersonThatCanDance : IPerson {
public void Arrive(Party party) {
//Logic related to arriving
...
party.AddDancers(this);
}
public void Dance() {
//Logic related to dancing
...
}
}
public class PersonThatCannotDance : IPerson {
public void Arrive(Party party) {
//Logic related to arriving
...
}
}
public class Party {
private IPerson person1;
private IPerson person2;
ArrayList dancers = new ArrayList();
private void StartParty() {
person1.Arrive(this);
person2.Arrive(this);
}
public void AddDancers(PersonThatCanDance dancer) {
dancers.Add(dancer);
}
private void StartMusic() {
for (var dancer in dancers) {
dancer.Dance();
}
}
}
A possibly more idiomatic alternative, is going by events.
public class PersonThatCanDance : IPerson {
public void Arrive(Party party) {
//Logic related to arriving
...
party.OnCueMusic(this.Dance);
}
...
}
public class Party {
public delegate void Dance();
ArrayList musicEvents = new ArrayList();
...
public void OnCueMusic(Dance dance) {
musicEvents.Add(dance);
}
private void StartMusic() {
for (var musicEvent in musicEvents) {
musicEvent();
}
}
}

How to increase a derived class value

I am modelling a program that simulates driving and refueling cars and trucks. So this is what I have done so far:
public abstract class Vehicle
{
protected Vehicle(double fuelQuantity, double fuelConsumption)
{
this.FuelQuantity = fuelQuantity;
this.FuelConsumption = fuelConsumption;
}
public double FuelQuantity { get; protected set; }
public double FuelConsumption { get; protected set; }
public abstract string Drive(double distance);
public abstract void Refuel(double liters);
}
public class Car : Vehicle
{
public Car(double fuelQuantity, double fuelConsumption) : base (fuelQuantity, fuelConsumption)
{
}
public override string Drive(double distance)
{
}
public override void Refuel(double liters)
{
}
}
So, I want to increase the value of the fuel consumption of the cars with 0.9 liters (it's summer, so cars use air conditioners). Where this can be done? I don't want to do it in the constructor because I don't think it's okay.
This would be a good place to add a decorator.
Some pseudo code (not complete!) but hopefully you get the idea.
public class VehicleDecorator : Vehicle
public VehicleDecorator(Vehicle vehicle)
{
this.vehicle = vehicle;
}
public class VehicleWithAc : VehicleDecorator
public VehicleWithAc(Vehicle vehicle) : base(vehicle){}
public override double FuelConsumption {
get{
return base.FuelConsumption+0.9 } }
Then in your program, create your car and decorate it with a VehicleWithAc decorator
Program
var baseCar = new Car();
var summerDriver = new VehicleWithAc(baseCar)
I think the problem you have is that you're passing fuelConsumption as a single variable in to the constructor, thereby stating
This is the fuel consumption of the car, full stop.
As you've found out, working through the problem - fuel consumption isn't a static thing, it's dependant on other variables, such as whether the AC is on. Doug was getting close with his mention of the decorator, but I think it can be a little simpler, but more flexible.
I think you should still pass a fuel consumption figure in, and for simplicitys sake, we'll call it baseFuelConsumption. Remember, vehicles are usually graded on urban, and highway fuel consumptions as they are generally different, but for the purposes of this, we'll ignore it.
Leaving out distance travelled etc, we have:
public abstract class Vehicle
{
private readonly double _baseFuelConsumption;
protected double BaseFuelConsumption => _baseFuelConsumption;
protected Vehicle(double baseFuelConsumption) => _baseFuelConsumption = baseFuelConsumption;
public virtual double ActualFuelConsumption => BaseFuelConsumption;
}
So, how much extra fuel consumption does an AC use? Let's take Doug's answer as a base-point, and give that to our car....
public class Car : Vehicle
{
private const double _ACModifier = 0.9;
public Car()
:base(1)
{
}
public bool IsACOn { get; set; }
public override double ActualFuelConsumption
{
get
{
double consumption = base.ActualFuelConsumption;
consumption += IsACOn ? _ACModifier : 0;
return consumption;
}
}
}
Now, for the purposes of your simulation you can switch the AC on and off, over time, and measure the ActualFuelConsumption property over time.
If you want to use this stracture you have to set custom rules for properties.
public abstract class Vehicle
{
protected Vehicle(double fuelQuantity, double fuelConsumption)
{
this.FuelQuantity = fuelQuantity;
this._fuelConsumption = fuelConsumption;
this.FuelConsumption = fuelConsumption;
}
public double FuelQuantity { get; protected set; }
private double _fuelConsumption { get; set; }
public double FuelConsumption {
get { return _fuelConsumption; }
protected set {
_fuelConsumption = (_fuelConsumption + 0.9);
} }
public abstract string Drive(double distance);
public abstract void Refuel(double liters);
}
Because your class is abstract and you dont have no overridable in properties in your derived class you cant have access to base properties.You can use condition in set for example
public double FuelConsumption {
get { return _fuelConsumption; }
protected set {
if(Issummer)
{
_fuelConsumption = (_fuelConsumption + 0.9);
}else{ _fuelConsumption =_fuelConsumption;}
} }

Polymorphism, Calling child method of parent

Hi everyone I am programming in Unity3d with C# and while I was writing my code I stumbled with a little issue, I write to you an example because I dont know explain me.
class Base
{
public string name;
}
class Derived : Base
{
public void Gun();
}
class BasePlayer
{
public Base x;
}
class SoldierPlayer : BasePlayer
{
}
The situation is this, I want to do something like that
SoldierPlayer.x.Gun();
But I don't know how do it
The real case is this
public class BasePlayerController : MonoBehaviour
{
public BasePlayerManager playerManager;
...
public class RobotPlayerController : BasePlayerController {
...
playerManager = gameObject.AddComponent<RobotPlayerManager>();
And I will use new methods
UPDATE 1
I did a example better, I want to do in Base Controller manager.user.energy and be treated as the next type RobotManager.RobotUser.energy
BaseController
BaseManager
BaseUser
class BaseController
{
BaseManager manager;
public virtual void Move(int x,int y)...
}
class BaseManager {
BaseUser user;
public virtual Pause(bool state);
}
class BaseUser {
int life
}
RobotController
RobotManager
RobotUser
class RobotController : BaseController
{
// manager as RobotManager?
public void Ray(int x,int y);
}
class RobotManager : BaseManager
{
// user as RobotUser?
}
class RobotUser : BaseUser
{
int energy;
}
UPDATE 2
I seek to do this
public Run()
{
RobotController rc = new RobotController();
rc.manager.energy;
}
You can't call SoldierPlayer.x.Gun(); because SoldierPlayer.x has type Base which has not method Gun(). OOP world and C# can provide you many solutions, your choose depends on your goals.
some of them (order by best practise):
1) Overriding Polymorphism. Add .Gun() method to Base class and implemend it in derived classes. For example
class Base
{
public string name;
public void virtual Gun()
{
Trace.Log("I'm base class, i can't do anything");
}
}
class Derived : Base
{
public override void Gun()
{
Consule.WriteLine("Hello i have gun");
}
}
class Derived2 : Base
{
public override void Gun()
{
Consule.WriteLine("Hello i have 2 guns");
}
}
2) Overloading Polymorphism In many source this method is mentioned like some kind of polymorphism AD-HOC
public void GunAction(Derived2 o)
{
o.Gun();
}
public void GunAction(Derived1 o)
{
o.Gun();
}
public void GunAction(Base o)
{
Trace.Log("I'm base class, i can't do anything");
}
3) is-cast
public void GunAction(Base o)
{
if(o is Derived1 )
o.Gun();
if(o is Derived2 )
o.Gun();
}
UPDATE 1 answering to your new requirements
class BaseController
{
public BaseManager manager;
...
class RobotController1 : BaseController
{
// manager as RobotManager? - no it is stil BaseManager
public void Ray(int x,int y);
}
class RobotController2 : BaseController
{
// manager as RobotManager? - yes. now it is RobotManager
public void Ray(int x,int y);
public RobotController2()
{
manager = new RobotManager();
}
}
public void Run()
{
var controller = new RobotController2();// you have RobotManager
controller.manager = new BaseManager();// it is again BaseManager
}

OOP implementation issue

The idea of the project is html renderer.
But i wanted to do it more dynamic by using Strategy design pattern(not sure if its strategy :D).
RenderStrategy:
public abstract class RenderStrategy
{
private Element _RenderElement;
public RenderStrategy(Element renderElement)
{
this._RenderElement = renderElement;
}
public abstract String Render();
}
Element:
public abstract class Element
{
public String Render(RenderStrategy strategy)
{
return strategy.Render();
}
}
my question is how should CompositeElement look like without the need of
RenderCompositeElementStrategy
I would do like this:
public interface IStrategy
{
string Render();
}
public class Element : IStrategy
{
public string Render() {
return "rendering for element";
}
}
public class CompositeElement : IStrategy
{
public string Render() {
return "rendering for composite element";
}
}
public class HTMLRenderer
{
private ISTrategy ele = new Element();
private IStrategy comp = new CompositeElement();
private IStrategy curr;
public HTMLREnderer(){
curr = ele; //i set default here to Element, but you can change it base on your need
}
public void RenderNow(){
Console.WriteLine(curr.Render());
//change your strategy accordingly to your need here, may be?
}
}

Nested class that inherits from its generic parent class

is this possible to somehow, have this scenario, where A.N inherits code from A with this code example?
The reason for setting it up like this, is that I need multiple classes that inherit from Base<TType> and the Nested : Base<TType> where the server has the base only, and the client has the extended Nested. This way, it would be easy to use the code, where they would have some shared code between themselves & each other.
The problem is that I would have to write identical code inside the
A and A.N
B and B.N
C and C.N
etc.
I have solved this temporarily, by replacing the Nested abstract class, with an Interface and doing
A.N : A, INested, but now I have to rewrite the Base<TType>.Nested code again inside all the Nested classes. For now, the nested class is small & managable.
hope this isn't a confusing question...
public abstract class Base<TType> where TType : class
{
public TType data;
internal void CommonCodeForAll() { }
public abstract void Update();
public abstract class Nested : Base<TType>
{
public abstract void Input();
}
}
public class A : Base<someClass>
{
public float Somevariable;
public void SpecificFunctionToA() { }
public override void Update()
{
// code that gets executed on server & client side that is unique to A
}
public class N : A.Nested
{
public override void Input()
{
if (data.IsReady()) { Somevariable *= 2; }
SpecificFunctionToA();
}
}
}
public class B : Base<anotherClass>
{
public float Somevariable;
public int index;
public int[] Grid;
public void SomethingElse() { }
public override void Update()
{
// code that gets executed on server & client side that is unique to B
}
public class N : B.Nested
{
public override void Input()
{
if (Grid[index] == -1) { SomethingElse(); }
data.Somevariable = Grid[index];
}
}
}
Edit:
I updated the code example to show what I'm trying to achieve.
Why I am trying to do this, is to keep the physics, networking & User input seperate.
There are multiple different controllers where each one has their own pack & unpacking functions, controller identity & access to the physics engine.
I have a solution using ecapsulation of classes instead of inheritance.
public abstract class BaseGeneric<T>
{
T data;
// ctor
protected BaseGeneric(T data)
{
this.data=data;
}
// methods
public abstract void Update();
// properties
public T Data
{
get { return data; }
set { data=value; }
}
// base nested class
public abstract class BaseNested<B> where B : BaseGeneric<T>
{
protected B #base;
// ctor
protected BaseNested(B #base)
{
this.#base=#base;
}
// methods
public abstract void Input(T data);
public void Update() { #base.Update(); }
// properties
public T Data
{
get { return #base.data; }
set { #base.data=value; }
}
}
}
// implementation base
public class Base : BaseGeneric<int>
{
// ctor
protected Base(int data) : base(data) { }
//methods
public override void Update()
{
this.Data+=1;
}
// implemented nested class
public class Nested : Base.BaseNested<Base>
{
// ctor
public Nested(int data) : base(new Base(data)) { }
public Nested(Base #base) : base(#base) { }
// methods
public override void Input(int data)
{
this.Data=data;
}
}
}
class Program
{
static void Main(string[] args)
{
// new implemented class with value 0
var nested=new Base.Nested(0);
// set value to 100
nested.Input(100);
// call update as implemented by `Base`.
nested.Update();
}
}

Categories

Resources