Delphi классы и методы.Нужна реализация одного метода для нескольких классов - PullRequest
0 голосов
/ 06 марта 2019

Так, например, у меня есть классы овощей для фермы.

TVegetable = class

TCarrot = class(TVegetable)
TTomato = class(TVegetable)

Мне нужны два разных класса каждого овоща, один для супермаркетов, а другой для фабрик.

TCarrotSupermarket = class(TCarrot)
TCarrotFactory = class(TCarrot)

Эти классы идентичны, за исключением кода для одного метода:

procedure Utilization;

TCarrotSupermarket.Utilization работает с супермаркетами, TCarrotFactory.Utilization работает с фабриками.

Один идентичный код для Utilization Iнужно для TCarrotSupermarket.Utilization, TTomatoSupermarket.Utilization, TPotatoSupermarket.Utilization и другого кода для TCarrotFactory.Utilization, TTomatoFactory.Utilization, TPotatoFactory.Utilization.

Как лучше всего писать код для Utilization только дважды(для супермаркетов и фабрик) и использовать его в надлежащих классах?

Ответы [ 2 ]

1 голос
/ 06 марта 2019

Добро пожаловать в Шаблон дизайна . Ваш случай Стратегия паттерна

class TStrategyVegetable = class(TVegetable)
  FUtil: TUtilization
public
  procedure Create(util: TUtilization);
  procedure Utilization();
end

procedure TStrategyVegetable.Create(util: TUtilization)
begin
  FUtil := util
end
procedure TStrategyVegetable.Utilization;
begin
  FUtil.Utilization;
end

Затем в коде:

carrotSupermarket = TCarrotSupermarket.Create(TCarrotSupermarketUtil.Create);
carrotFactory = TCarrotFactory.Create(TCarrotFactoryUtil.Create);
0 голосов
/ 07 марта 2019

Вот некоторый псевдокод, попадающий в решение с использованием разрешения метода интерфейса. (Не проверено, даже не скомпилировано, но оно должно указать вам правильное направление)

IFactoryInterface=interface(IUnknown) ['{someGUID}']
  procedure Utilization;
end;

ISuperMarketInterface=interface(IUnknown) ['{AnotherGUID}']
  procedure Utilization;
end;

TVegetable = class (TSomeObject,IFactoryInterface,ISupermarketInterface)
protected
  // the routines tha do the actual implementation
  // can be regular virtual, dynamic, or whatever
  procedure FactoryUtilization; 
  procedure SuperMarketUtilization; 
  // link up the interfaces using method resolution
  procedure IFactoryInterface.Utilization=FactoryUtilization;
  procedure ISupermarketInterface.Utilization=SuperMarketUtilization;

{ in case not derived from TInterfacedObject, 
  You'll have to add _AddRef,_Release and 
  QueryInterface methods too }

end;

// the other implementations can be as before
TCarrot = class(TVegetable)
TTomato = class(TVegetable)

Тогда при использовании кода он должен выглядеть примерно так:

VAR lSOmeVegetable,lAnotherVegetable:TVegetable;
... 
lSomeVegetable:=TCarrot.Create
lanotherVegetable:=Tomato.Create
...
// call using buolt-in type checking
(lSOmeVegetable as IFactoryInterface).Utilization;
(lAnotherVegetable as ISuperMarketInterface).Utilization;

Или иначе, используя подпрограмму поддержки

VAR lFactory:IFactoryInterface;
...
if supports(lSomeVegetable,IFactoryInterface,lFactory) then
  lFactory.Utilization
...

Надеюсь, это вам немного поможет. Вот указатель на некоторую соответствующую документацию

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...