设计模式(一):简单工厂、工厂模式、抽象工厂
提示:
UML类图中,空心三角实线,为继承关系;
空心三角虚线,为实现接口;
实线箭头,为关联关系;
虚线箭头,为依赖关系;
实心菱形实线箭头,为组合(合成)关系;
空心菱形实线箭头,为聚合关系;
开闭原则:对于扩展是开放的,对于修改是关闭的。
1.简单工厂(以计算器为例)
优点:
在简单工厂类里包含了必要的逻辑判断,客户端只需要传参调用简单工厂的方法即可自动创建相应具体运算类,
去除了与具体运算类的依赖,封装了具体运算类的创建。
缺点:
①当运算有复杂的多层等级结构时,可能造成简单工厂中逻辑过于复杂,极易出错,导致工厂故障,影响所有运算。
②简单工厂内通常使用静态工厂方法,使得即使子类继承了简单工厂类,也不能实现该方法的多态(重载、重写)。
③每新增/修改一个具体运算类,就需要修改简单工厂类,添加/修改一种case情形,违反了开闭原则。 (可用反射来避免分支判断)
适用范围:简单工厂负责创建的对象比较少,且用户不关注对象的创建逻辑及细节。
客户端:
用户填写参数 : num1, num2, operator
实现 : Operation oper = SimpleFactory.createOperation(operator); //直接入参,选择运算符
oper.setNum1(num1);
oper.setNum2(num2);
double result = oper.getResult();
简单概括:调用一个简单工厂去创建所需要的各种具体运算类。
2.工厂模式(以计算器为例)
优点:
①对简单工厂模式进行了抽象,有一个抽象的工厂接口,衍生所有工厂。
②符合开闭原则,可实现复杂的层次结构,扩展性良好,封装了具体运算类的创建,易于更换运算。
③由客户端来决定实例化哪个工厂来实现运算类,即将原简单工厂内的判断移到了客户端来进行。
缺点:
不易维护,新增/修改一个具体运算类,就需要添加/修改一个具体运算类和其工厂类,加大了额外的开发量。若需要同时修改多个具体运算类,会变得复杂。
适用范围:一个类希望由其子类来指定它要创建的对象时适用,且用户不关注对象的创建逻辑及细节。
客户端:
用户填写参数 : num1, num2,(选择具体运算工厂)
实现 : IFactory operationFactory= new AddFactory(); //声明工厂类,选择实例化加法类工厂
Operation oper = operationFactory.createOperation(); //实例化加法类
oper.setNum1(num1);
oper.setNum2(num2);
double result = oper.getResult();
简单概括:一个抽象工厂接口,多个具体工厂来实现,再由每个工厂生产各自的具体产品,即调用具体工厂生产具体产品。
3.抽象工厂(以切换连接不同数据库的方式为例)
原始UML类图:
用简单工厂改进抽象工厂后的UML类图:
优点:
①基于工厂方法模式,用来创建一组相关或相互依赖的对象(多个),而工厂模式只是创建一个对象
②产品创建具体实例的过程和客户端分离,客户端只能通过抽象接口操纵实例,易于替换成它类产品
缺点:
不易扩展,新增产品需要扩展工厂接口,则需要修改抽象工厂和诸多子类。(反射可简化)
适用范围:创建一组相关或相互依赖的对象,且用户不关注对象的创建逻辑及细节。
客户端:
用户填写参数 :
实现 : IUser iu = DataAccess.createUser();
iu.insert(new User()); //新增
iu.getUser(1); //查询ID
IDepartment id = DataAccess.createdepartment();
id.insert(new Department());//新增
id.getDepartment(1); //查询ID
简单概括:调用统一的对外抽象接口,来创建一组相关或相互依赖的对象。
Ps:(UML图来自《大话设计模式》一书,这书很好,建议细读)