[Musings] 今天开始了设计模式的滚动上手学习,来增强下整体的设计思路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 package org.example.factory.playground;public class FactoryMain { public static void main (String[] args) { System.out.println("=== 工厂模式演示 ===" ); ButtonFactory buttonFactory = new ButtonFactory (); TextBoxFactory textBoxFactory = new TextBoxFactory (); Button button = buttonFactory.createButton("windows" ); TextBox textBox = textBoxFactory.createTextBox("windows" ); button.click(); button.print(); textBox.input(); textBox.print(); System.out.println("\n=== 抽象工厂模式演示 ===" ); UIFactory macUIFactory = new MacUIFactory (); UIFactory windowsFactory = new WindowsUIFactory (); Button macButton = macUIFactory.createButton(); TextBox macTextBox = macUIFactory.createTextBox(); macButton.click(); macButton.print(); macTextBox.input(); macTextBox.print(); Button windowsButton = windowsFactory.createButton(); TextBox windowsTextBox = windowsFactory.createTextBox(); windowsButton.click(); windowsButton.print(); windowsTextBox.input(); windowsTextBox.print(); } } package org.example.factory.playground;abstract class Button { public void click () { System.out.println("button clicked" ); } abstract void print () ; } package org.example.factory.playground;class ButtonFactory { public Button createButton (String type) { switch (type) { case "windows" : return new WindowsButton (); case "mac" : return new MacButton (); default : return new WindowsButton (); } } } package org.example.factory.playground;class MacButton extends Button { @Override void print () { System.out.println("Mac Button print!" ); } @Override public void click () { System.out.println("Mac button click!" ); } } package org.example.factory.playground;class MacTextBox extends TextBox { @Override void print () { System.out.println("Mac TextBox input!" ); } } package org.example.factory.playground;public class MacUIFactory extends UIFactory { @Override Button createButton () { return new MacButton (); } @Override TextBox createTextBox () { return new MacTextBox (); } } package org.example.factory.playground;abstract class TextBox { public void input () { System.out.println("input activate" ); } abstract void print () ; } package org.example.factory.playground;class TextBoxFactory { public TextBox createTextBox (String type) { switch (type) { case "windows" : return new WindowsTextBox (); case "mac" : return new MacTextBox (); default : return new WindowsTextBox (); } } } package org.example.factory.playground;public abstract class UIFactory { abstract Button createButton () ; abstract TextBox createTextBox () ; } package org.example.factory.playground;class WindowsButton extends Button { @Override void print () { System.out.println("Windows Button print!" ); } @Override public void click () { System.out.println("Windows button click!" ); } } package org.example.factory.playground;class WindowsTextBox extends TextBox { @Override void print () { System.out.println("WindowsTextBox input!" ); } } package org.example.factory.playground;public class WindowsUIFactory extends UIFactory { @Override Button createButton () { return new WindowsButton (); } @Override TextBox createTextBox () { return new WindowsTextBox (); } }
这里包含了抽象工厂模式和工厂模式,主要区别可以这么记忆
工厂模式: 聚焦于产品,打个比方就是 手机专卖店: iphone手机,huawei手机,xiaomi手机 音箱专卖店: bose音箱, apple音箱,小爱音箱
抽象工厂: 聚焦于产品簇, 打个比方就是 原木风家居: 原木风桌子,原木风椅子,原木风床
所以:
工厂模式适合: 产品种类相对独立,不需要强一致的风格 客户端需要灵活组合不同来源的产品
抽象工厂模式适合: 需要确保一系列产品的兼容性和一致性 产品间有强烈的主题/风格关联 约束用户只使用同一系列的产品
工厂模式的实际应用 : * // BeanFactory - 最经典的工厂模式 ApplicationContext context = new ClassPathXmlApplicationContext(“beans.xml”); UserService userService = context.getBean(“userService”, UserService.class);
// Log4j2 / SLF4J Logger logger = LoggerFactory.getLogger(MyClass.class); // 根据配置返回Log4jLogger、JULLogger等具体实现
// JDBC DriverManager Connection conn = DriverManager.getConnection(url, user, password); // 根据URL返回MySQL、PostgreSQL、Oracle等具体连接
抽象工厂模式的实际应用 // JavaFX / Swing 的主题系统 // 你实现的例子就是最典型的应用! UIFactory factory = Platform.getUIFactory(); Button btn = factory.createButton(); Menu menu = factory.createMenu();
// 不同数据库的DAO工厂 DAOFactory factory = DAOFactory.getFactory(DBType.MYSQL); UserDAO userDAO = factory.getUserDAO(); OrderDAO orderDAO = factory.getOrderDAO(); // 保证所有DAO使用同一种数据库
// 不同消息中间件的工厂 MessageFactory factory = MessageFactory.getKafkaFactory(); Producer producer = factory.createProducer(); Consumer consumer = factory.createConsumer(); AdminClient admin = factory.createAdminClient();
// AWS / Azure / Google Cloud 的抽象工厂 CloudFactory factory = CloudFactory.getAWSFactory(); StorageService storage = factory.createStorageService(); ComputeService compute = factory.createComputeService(); DatabaseService db = factory.createDatabaseService();
第二个讨论下 Singleton
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class EagerSingleton { private static instance : EagerSingleton = new EagerSingleton (); private constructor ( ) { console .log ("EagerSingleton 实例被创建" ); } public static getInstance (): EagerSingleton { return EagerSingleton .instance ; } public showMessage (): void { console .log ("Hello from EagerSingleton!" ); } } const eager1 = EagerSingleton .getInstance ();const eager2 = EagerSingleton .getInstance ();console .log (eager1 === eager2); class LazySingleton { private static instance : LazySingleton | null = null ; private constructor ( ) { console .log ("LazySingleton 实例被创建" ); } public static getInstance (): LazySingleton { if (LazySingleton .instance === null ) { LazySingleton .instance = new LazySingleton (); } return LazySingleton .instance ; } public showMessage (): void { console .log ("Hello from LazySingleton!" ); } } const lazy1 = LazySingleton .getInstance (); const lazy2 = LazySingleton .getInstance ();console .log (lazy1 === lazy2);
唯一的区别就是懒汉和饱汉,懒汉就是在调用的时候才生成,容易造成多线程问题,饱汉就是直接初始化要用的时候直接返回,天生的线程安全,但资源浪费