Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save amalChandran/34ab9f1adf80bb83476a0cc5710e4138 to your computer and use it in GitHub Desktop.
Save amalChandran/34ab9f1adf80bb83476a0cc5710e4138 to your computer and use it in GitHub Desktop.
Solid Flutter - Open-Closed Principle Example
import 'package:flutter/material.dart';
// Bad Example: Violating Open-Closed Principle
class BadButton extends StatelessWidget {
final String type;
final String label;
final VoidCallback onPressed;
BadButton({
required this.type,
required this.label,
required this.onPressed,
});
@override
Widget build(BuildContext context) {
switch (type) {
case 'primary':
return ElevatedButton(
style: ElevatedButton.styleFrom(primary: Colors.blue),
onPressed: onPressed,
child: Text(label),
);
case 'secondary':
return OutlinedButton(
style: OutlinedButton.styleFrom(primary: Colors.blue),
onPressed: onPressed,
child: Text(label),
);
case 'danger':
return ElevatedButton(
style: ElevatedButton.styleFrom(primary: Colors.red),
onPressed: onPressed,
child: Text(label),
);
default:
return TextButton(
onPressed: onPressed,
child: Text(label),
);
}
}
}
// Good Example: Following Open-Closed Principle
abstract class ButtonStyle {
Widget build(String label, VoidCallback onPressed);
}
class PrimaryButtonStyle implements ButtonStyle {
@override
Widget build(String label, VoidCallback onPressed) {
return ElevatedButton(
style: ElevatedButton.styleFrom(primary: Colors.blue),
onPressed: onPressed,
child: Text(label),
);
}
}
class SecondaryButtonStyle implements ButtonStyle {
@override
Widget build(String label, VoidCallback onPressed) {
return OutlinedButton(
style: OutlinedButton.styleFrom(primary: Colors.blue),
onPressed: onPressed,
child: Text(label),
);
}
}
class DangerButtonStyle implements ButtonStyle {
@override
Widget build(String label, VoidCallback onPressed) {
return ElevatedButton(
style: ElevatedButton.styleFrom(primary: Colors.red),
onPressed: onPressed,
child: Text(label),
);
}
}
class DefaultButtonStyle implements ButtonStyle {
@override
Widget build(String label, VoidCallback onPressed) {
return TextButton(
onPressed: onPressed,
child: Text(label),
);
}
}
class GoodButton extends StatelessWidget {
final ButtonStyle style;
final String label;
final VoidCallback onPressed;
GoodButton({
required this.style,
required this.label,
required this.onPressed,
});
@override
Widget build(BuildContext context) {
return style.build(label, onPressed);
}
}
// Usage example
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
GoodButton(
style: PrimaryButtonStyle(),
label: 'Primary Button',
onPressed: () {},
),
GoodButton(
style: SecondaryButtonStyle(),
label: 'Secondary Button',
onPressed: () {},
),
GoodButton(
style: DangerButtonStyle(),
label: 'Danger Button',
onPressed: () {},
),
// Easy to extend with new button styles without modifying existing code
GoodButton(
style: CustomButtonStyle(),
label: 'Custom Button',
onPressed: () {},
),
],
);
}
}
// Extending with a new button style without modifying existing code
class CustomButtonStyle implements ButtonStyle {
@override
Widget build(String label, VoidCallback onPressed) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.green,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
onPressed: onPressed,
child: Text(label),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment