继承父类实例化Db vs 单独实例化:哪种服务器开销更低?
Great question! Let’s break this down clearly so you understand both the efficiency impact and the practical tradeoffs.
First off, let’s get the core question out of the way: for most real-world applications, there is almost no measurable difference in server overhead between these two approaches. Here’s why:
What’s Happening Under the Hood?
Both routes end up creating one Db instance per subclass instance:
- Route 1 (Parent Class Template):When you instantiate a child class (like
Login), the parent constructor runs (since your child constructor doesn’t override it explicitly—though pro tip: always callparent::__construct();in child constructors for clarity). This creates aDbinstance tied to that child object, same as Route 2. - Route 2 (Per-Class Instantiation):Each subclass creates its own
Dbinstance directly in its constructor. No shared instances here, just one per object, same as Route 1.
Unless you’re running an extreme high-concurrency app (think tens of thousands of requests per second), the tiny difference in execution path won’t show up in your server metrics.
The Real Win: Maintainability
Where Route 1 shines is code maintainability, which indirectly saves you (and your server) headaches down the line:
- Less repeated code: If you ever need to adjust how
Dbis instantiated—say, adding database credentials, switching to a different driver, or adding error handling—you only have to update the parent class. No hunting down every subclass that creates aDbinstance. - Consistent patterns: All classes that need database access follow the same setup, so there’s no risk of inconsistent
Dbconfigurations across your codebase.
If you want to reduce Db instance overhead for real, these approaches are more impactful than choosing between your two routes:
Singleton Pattern
Make the Db class enforce a single instance across your app, so you only create it once per request:
class Db { private static $instance; // Prevent external instantiation private function __construct() {} public static function getInstance() { if (!self::$instance) { self::$instance = new Db(); } return self::$instance; } }
Then use it in your parent (or child) class like this:
$this->db = Db::getInstance();
This cuts down on repeated Db initialization costs, which can add up in busy apps.
Dependency Injection (DI)
Pass a pre-created Db instance into your classes instead of instantiating it inside them. This is even more flexible, especially for testing:
class Login { private $db; public function __construct(Db $db) { $this->db = $db; } } // Usage $dbInstance = new Db(); $loginHandler = new Login($dbInstance);
DI lets you reuse the same Db instance across multiple classes and swap in mock databases for testing without changing your core code.
- Between your two original options: no meaningful server overhead difference—both create one
Dbinstance per subclass object. - Go with Route 1 (parent class inheritance) for cleaner, more maintainable code.
- If performance is a top concern, use singleton or dependency injection to reduce
Dbinstantiation frequency.
内容的提问来源于stack exchange,提问作者Mark

