设计模式(二)- 建造者模式 /反射+抽象工厂
好久没发动态了,基于这端时间一只忙于经销商的开发,现在终于有了一些空余时间。这次继续上次设计模式,继续写我的笔记。。。。。。
建造者模式
建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程就可以创建不同的表示。
建造者模式又称为“生成器模式”,建造者模式可以将一个产品的内部表象与产品的生产过程分割开来,从而可以使一个建造过程生成具有不同的内部产品对象。当使用建造者模式,那么用户就只需要指定需要建造的类型就可以得到它们,而不就不需要知道具体建造的过程和细节。
代码体现
/**
* 产品类
*/
public class Product {
List<String> parts = new ArrayList<>();
public void add(String part) {
parts.add(part);
}
public void show() {
for (int i = 0, length = parts.size(); i < length; i ++) {
System.out.println("=============part========== "+parts.get(i));
}
}
}
/**
* 抽象建造者类
*/
public abstract class Builder {
public abstract void buildPartA();
public abstract void buildPartB();
public abstract Product getResult();
}
/**
* 具体建造者1
*/
public class BuilerOne extends Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.add("A部件");
}
@Override
public void buildPartB() {
product.add("B部件");
}
@Override
public Product getResult() {
return product;
}
}
/**
* 具体建造者2
*/
public class BuilderTwo extends Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.add("C部件");
}
@Override
public void buildPartB() {
product.add("D部件");
}
@Override
public Product getResult() {
return product;
}
}
/**
* 指挥者类
*/
public class Director {
public void construct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
}
}
/**
* 客户端
*/
public class ClientA {
public static void main(String[] args) {
Director director = new Director();
Builder b1 = new BuilerOne();
Builder b2 = new BuilderTwo();
director.construct(b1);
Product product1 = b1.getResult();
product1.show();
director.construct(b2);
Product product2 = b2.getResult();
product1.show();
}
}
运行结果:
建造者主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。优点:使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义个具体的建造者就可以了。
总结:建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式适用的模式。
抽象工厂模式
抽象工厂模式:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。
以平常最简单的开发为例,在开发中我们经常会用到持久化的框架(mybatis,hibernate 等)连接相应的数据库,当没有抽象工厂模式,我们写的代码会很“丑”,一旦切换数据库修改起来就会十分繁琐。当我们使用了抽象模式就会减轻很多的负担。
反射+抽象工厂模式的数据访问程序
/**
* 部门表domain类
*/
public class Department {
private int id;
private String deptName;
}
public interface IDepartment {
void insert(Department department);
Department getDepartment(int id);
}
/**
* 模拟访问sql server
*/
public class SqlserviceDepartment implements IDepartment {
public void insert(Department department) {
System.out.println("add a data in sql server DB!");
}
public Department getDepartment(int id) {
System.out.println("show a data by id in sql server!");
return null;
}
}
/**
* 模拟访问Access
*/
public class AccessDepartment implements IDepartment {
public void insert(Department department) {
System.out.println("add a data in Access DB!");
}
public Department getDepartment(int id) {
System.out.println("show a data by id in Access DB!");
return null;
}
}
/**
* 访问Department表对象的抽象的工厂借口
*/
public interface IFactory {
IDepartment createDepartment();
}
/**
* 实现IFactory接口,实例化SqlServerDepartment
*/
public class SqlServerFactory implements IFactory{
public IDepartment createDepartment() {
return new SqlserviceDepartment();
}
}
/**
* 实现IFactory接口,实例化AccessDepartment
*/
public class AccessFactory implements IFactory{
public IDepartment createDepartment() {
return new AccessDepartment();
}
}
public class Client {
public static void main(String[] args) {
Department department = new Department();
IFactory iFactory = new SqlServerFactory();
IDepartment iDepartment = iFactory.createDepartment();
iDepartment.insert(department);
}
}
上述代码中如果将SqlServer切换为Access数据库连接,需修改new SqlServerFactory()->new AccessFactory();但当我们引用的地方太多的时候,修改起来还是比较麻烦的。这是用反射就可以完美解决
public class DataAccess {
//数据库连接包名
private static String dataName = "abstractModle.SqlServerFactory";
public static IDepartment createDepartment() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
return (IDepartment) Class.forName(dataName).newInstance();
}
}
上述中如果要切换数据库,需要修改dataName的名称,需要重新编译,在不修改程序的情况下可以,添加数据库连接信息的配置,通过读取配置信息的方法读取变量值,这样切换时就只需要修改配置文件值,不需重新编译代码了,耦合度大大降低。