How I can design decorator pattern in system verilog.
I tried to write decorator pattern based on Java code on website, but it does not work.
It seems object chaining is terminated at the one reference and no 2nd or more reference is observed. I ran below in VCS and IES.
The situation of the following sample code is to calculate total cost(Coffee::cost()) when add some toppings (Milk or Mocha) on coffee.
class Coffee;
function new();
endfunction
function int cost();
return 1000;
endfunction
endclass
virtual class DecoratorBase extends Coffee;
pure virtual function int cost();
pure virtual function Coffee decorate(Coffee coffee);
endclass
class Mocha extends DecoratorBase;
Coffee coffee;
function new();
endfunction
function Coffee decorate(Coffee coffee);
this.coffee=coffee;
return this.coffee;
endfunction
function int cost();
return coffee.cost()+10;
endfunction
endclass
class Milk extends DecoratorBase;
Coffee coffee;
function new();
endfunction
function Coffee decorate(Coffee coffee);
this.coffee=coffee;
return this.coffee;
endfunction
function int cost();
return coffee.cost()+100;
endfunction
endclass
module tb();
initial begin
Coffee c1;
Mocha d1, d2;
Milk d3;
Coffee x1; // pointer to Coffee object
c1 = new();
d1 = new(); d2 = new(); d3 = new();
x1=d1.decorate(c1);
x1=d2.decorate(x1);
x1=d3.decorate(x1);
// $display("## x1 cost is %d", d3.cost()); // 1100 (1000+ 100 is executed)
$display("## x1 cost is %d", x1.cost()); // 1000 (I expect to yield 1120; 1000+10+10+100)
end
endmodule // tb
In Java code:
class Coffee
{
public cost(){return 1.5;}
}
// Abstract Decorator
class CondimentDecorator extends Coffee
{
}
// Concrete Decorator
class Mocha extends ComdimentDecorator
{
Coffee coffee;
public Mocha(Coffee coffee){this.coffee = coffee;}
public cost(){return .2 + coffee.cost();}
}
class Milk extends ComdimentDecorator
{
Coffee coffee;
public Milk(Coffee coffee){this.coffee = coffee;}
public cost(){return .5 + coffee.cost();}
}
-----
Coffee c1 = new Coffee();
c1 = new Mocha(c1);
c1 = new Mocha(c1);
c1 = new Milk(c1);
c1.cost(); //
Thank you for your attention.
Regards