学习设计模式——工厂方法
2015-08-12 10:03
302 查看
这里要先感谢《研磨设计模式》一书的作者,在讲述IoC/DI(控制反转/依赖注入)的时候深入浅出,让我有了清晰的理解,谢谢。
关于IoC/DI
依赖注入:应用程序依赖容器创建并注入它所需要的外部资源
控制反转:容器控制应用程序,有容器反向地向应用程序注入其所需要的外部资源
有效的分离了对象和所需要的外部资源,松耦合,有利于复用
适用于:
让父类在不知道具体实现的情况下,完成自身功能的调用,将具体的实现延迟到子类来实现。
子类通常是做选择来实现产品对象,而非直接实现功能。
优点:
良好的封装性,代码结构清晰——平行化代码结构,有什么样的产品对象就有什么样的产品工厂。或者由带参数的总工厂来生成所有的产品对象。
扩展性非常强——只需要适当的修改具体工厂类或者扩展一个工厂类,就可以实现变化。
可以屏蔽具体的产品类。
典型的解耦模式。
缺点:
具体产品对象和工厂方法的耦合。(关于这点个人认为是理所应当的,不算缺点,毕竟总有类是耦合的,在子类中耦合是解耦父类的一种途径,符合里氏替换原则)
产品类:
工厂类:
客户端:
结果:
it’s ProductA
扩展:
生成单例的工厂类:
关于IoC/DI
依赖注入:应用程序依赖容器创建并注入它所需要的外部资源
控制反转:容器控制应用程序,有容器反向地向应用程序注入其所需要的外部资源
有效的分离了对象和所需要的外部资源,松耦合,有利于复用
适用于:
让父类在不知道具体实现的情况下,完成自身功能的调用,将具体的实现延迟到子类来实现。
子类通常是做选择来实现产品对象,而非直接实现功能。
优点:
良好的封装性,代码结构清晰——平行化代码结构,有什么样的产品对象就有什么样的产品工厂。或者由带参数的总工厂来生成所有的产品对象。
扩展性非常强——只需要适当的修改具体工厂类或者扩展一个工厂类,就可以实现变化。
可以屏蔽具体的产品类。
典型的解耦模式。
缺点:
具体产品对象和工厂方法的耦合。(关于这点个人认为是理所应当的,不算缺点,毕竟总有类是耦合的,在子类中耦合是解耦父类的一种途径,符合里氏替换原则)
产品类:
public interface Product { void doSomething(); } public class ProductA implements Product { //这里私有没有特别的意思,就是不想被外界直接new private ProductA(){ } public void doSomething() { System.out.println("it's ProductA"); } } public class ProductB implements Product { private ProductB(){ } public void doSomething() { System.out.println("it's ProductB"); } }
工厂类:
public abstract class Factory { //这个就是工厂方法,是该模式的核心 public abstract Product createProduct(); //这里通过访问工厂的方法来调用具体产品的方法 //这样产品被封装的很好,而且扩展很强 public void doSomething() { Product p = createProduct(); if(p!=null){ p.doSomething(); } } } public class FactoryA extends Factory { public Product createProduct() { try { Constructor<?> c = Class.forName(ProductA.class.getName()).getDeclaredConstructor(); c.setAccessible(true); return (Product) c.newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } }
客户端:
public class Client { public static void main(String[] args) { Factory a = new FactoryA(); a.doSomething(); } }
结果:
it’s ProductA
扩展:
生成单例的工厂类:
public class SingletonFactory { private static final Map<String, Object> objectMap = new HashMap<String, Object>(); public synchronized static <T> T createSingleton(Class<T> c) { T t = null; String className = c.getName(); try { if (!objectMap.containsKey(className)) { Class<?> c1 = Class.forName(className); Constructor<?> constructor = c1.getDeclaredConstructor(); constructor.setAccessible(true); t = (T) constructor.newInstance(); objectMap.put(className, t); } } catch (Exception e) { e.printStackTrace(); } return (T) objectMap.get(className); } public static void main(String[] args) { Product productA1 = SingletonFactory.createSingleton(ProductA.class); System.out.println(productA1); Product productB1 = SingletonFactory.createSingleton(ProductB.class); System.out.println(productB1); Product productA2 = SingletonFactory.createSingleton(ProductA.class); System.out.println(productA2); Product productB2 = SingletonFactory.createSingleton(ProductB.class); System.out.println(productB2); } }
相关文章推荐
- LeetCode题解:Valid Anagram
- Windows10的革命之路-全新UWP开发平台
- 【P2P网贷新手入门】详解借款标的种类及其风险
- Java多线程学习(二)---线程创建方式
- 云 + 端并重,柚子科技 APICloud 要做传统服务 B/S 架构到 Apps 转型的催化剂
- C# 删除时弹出提示框操作
- 解决IllegalStateException: Can not perform this action after onSaveInstanceState
- EasyUI学习笔记8:MIS开发利器_ datagrid插件(下)(终结篇)
- JQuery datatable
- Android应用与framework的socket通信实例
- MacOS下Python的多版本管理(pyenv)
- 如何禁用事件的浮升(div的子元素的点击事件会触发父元素的点击事件)
- MYSQL 主从服务器配置
- 介绍MFC参与设计模式框架(一个)
- 你们都是怎么阅读android系统源码的,用什么工具?
- js中数组的去重
- 字符个数统计
- UNIX网络编程卷一:第十四章 高级I/O
- LNMP--Nginx不记录指定文件日志
- 什么样的程序员最易涨薪?