patternphpMinor
Divide big class in subclasses
Viewed 0 times
subclassesdividebigclass
Problem
I have a very big class
Then I should be able to divide them as I want. For example:
But I should be able to call
How should I manage this division? Interfaces? Abstract classes? Inheritance? How?
Foo that should be divided into FooBar, FooUtility, FooBench, FooBranch. Each of this "subclasses" should have different methods. So that if Foo has:public function methodA();
public function methodB();
public function methodC();
public function methodZ();Then I should be able to divide them as I want. For example:
FooBar:
public function __construct($param);
public function methodA();
FooUtility:
public function __construct($param);
public function methodB();
FooBench:
public function __construct($param);
public function methodZ();
FooBranch:
public function __construct($param);
public function methodC();But I should be able to call
methodB() and methodZ() from the same class Foo.How should I manage this division? Interfaces? Abstract classes? Inheritance? How?
Solution
With Composition/Aggregation.
first define your interface for Foo collecting all the public methods it should expose from the components:
You could also create interfaces for the components and extend the Foo interface from those, e.g.
Note: it's not strictly necessary to have an interface collecting the other interfaces or to have an interface for Foo at all. However, since you should program against an interface and not a concrete implementation, it's cleaner.
Then implement that in your conrete Foo implementation:
Inject the various components through the ctor and then just have the methods on Foo delegate to the appropriate components.
You can use use a Factory or Builder to encapsulate creation of the complex Foo type. This will allow you to parametrize the subcomponents:
Note that Factory and Builder are creational patterns. They may control when and how objects are created, so if you want to reuse one of the components in subsequent calls to create, you may add logic to manage the component lifecycles in the factory/builder.
first define your interface for Foo collecting all the public methods it should expose from the components:
interface Foo
{
public function methodA();
public function methodB();
…
}You could also create interfaces for the components and extend the Foo interface from those, e.g.
interface Foo extends FooBar, FooUtility
{}Note: it's not strictly necessary to have an interface collecting the other interfaces or to have an interface for Foo at all. However, since you should program against an interface and not a concrete implementation, it's cleaner.
Then implement that in your conrete Foo implementation:
class FooImplementation implements Foo
{
public function __construct(FooBar $fooBar, FooUtility $fooUtility)
{
$this->fooBar = $fooBar;
$this->fooUtility = $fooUtility;
}
public function methodA()
{
return $this->fooBar->methodA();
}
public function methodB()
{
return $this->fooUtility->methodB();
}
…
}Inject the various components through the ctor and then just have the methods on Foo delegate to the appropriate components.
You can use use a Factory or Builder to encapsulate creation of the complex Foo type. This will allow you to parametrize the subcomponents:
class FooFactory
{
public function create($param1, $param2)
{
return new FooImplementation(
new FooBar($param1),
new FooUtility($param2)
);
}
}Note that Factory and Builder are creational patterns. They may control when and how objects are created, so if you want to reuse one of the components in subsequent calls to create, you may add logic to manage the component lifecycles in the factory/builder.
Code Snippets
interface Foo
{
public function methodA();
public function methodB();
…
}interface Foo extends FooBar, FooUtility
{}class FooImplementation implements Foo
{
public function __construct(FooBar $fooBar, FooUtility $fooUtility)
{
$this->fooBar = $fooBar;
$this->fooUtility = $fooUtility;
}
public function methodA()
{
return $this->fooBar->methodA();
}
public function methodB()
{
return $this->fooUtility->methodB();
}
…
}class FooFactory
{
public function create($param1, $param2)
{
return new FooImplementation(
new FooBar($param1),
new FooUtility($param2)
);
}
}Context
StackExchange Code Review Q#8410, answer score: 5
Revisions (0)
No revisions yet.