建造者模式
当问题注重对象的创建过程,并且要求创建同类对象的不同产品时用建造者模式。例如房子的构建,地基->钢筋工程->堆砌砖瓦->粉刷,注重创建过程,但是对于平房和楼房来说,过程是一样的但是相应步骤的实现是不一样的。
建造者模式的基本构成
Product定义了产品的部件
Abstract Builder规定Worker行为
real Worker定义了各产品部件的构建方法,并且创建出实际的产品,并且可有多个Worker,可以有多个不同产品实现(平房与楼房)
Director则主要控制产品制作的流程,可有多个Director,有多个种不同的流程
这样便将产品的构建与表现分离
//产品
public class Product {
// 产品部件
private String buildA;
private String buildB;
public String getBuildA() {
return buildA;
}
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public String getBuildB() {
return buildB;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
}
//抽象工人
public abstract class Builder {
// 创建产品零件
abstract void buildA();
abstract void buildB();
// 完工得到产品
abstract Product getProduct();
}
//工人
public class Worker extends Builder{
private Product product;
public Worker() {
product = new Product();
}
@Override
void buildA() {
product.setBuildA("A部件完成");
}
@Override
void buildB() {
product.setBuildB("B部件完成");
}
@Override
Product getProduct() {
return product;
}
}
//指挥工创建
public class Director {
//将产品交给抽象的builder,对于不同的Worker就有不同的实现
public Product build(Builder builder){
//控制builder的建造顺序
builder.buildA();
builder.buildB();
//返回产品
return builder.getProduct();
}
//测试
public static void main(String[] args) {
Director director=new Director();
Product product=director.build(new Worker());
}
}
链式编程取代director
//抽象工人
public abstract class Builder {
// 创建产品零件
abstract Builder buildA();
abstract Builder buildB();
// 完工得到产品
abstract Product getProduct();
}
public class Test{
public static void main(String[] args) {
//构建顺序可由我们自己控制
Product product=new Worker().buildA().buildB().getProduct();
}
}
工厂模式
我们假设有Car接口规定汽车的基本信息,类Tesla和Ferrari是Car的两种实现,顾客Consumer得到汽车的实例。
public class Consumer {
public static void main(String[] args) {
car car1=new Tesla();
car car2=new Ferrari();
}
}
若按照非工厂模式我们的得到实例需使用new,有两个问题:一是用new创建的话需要了解所有的接口(可能带有大量参数)和实现类;二是直接使用new相当于顾客创造汽车,意义不符。
静态工厂模式
现在加入第三方工厂,可以代替客户制造汽车,那么客户直接从CarFactory直接拿到车。
public class Consumer {
public static void main(String[] args) {
Car car1 = Carfactory.getCar("Ferrari");
Car car2 = Carfactory.getCar("Tesla");
}
}
public class Carfactory {
// 方法1
public static Car getCar(String carname){
if(carname.equals("Ferrari")){
return new Ferrari();
}
else if(carname.equals("Tesla")){
return new Tesla();
}
else {
return null;
}
}
// 方法2
public static Car getFerrari(){
return new Ferrari();
}
public static Car getTesla(){
return new Tesla();
}
}
静态工厂模式存在的问题是若扩展车的种类,则必须修改Carfactory的代码,不满足开闭原则。
工厂方法模式
在静态工厂模式的基础上,增加了工厂接口,那么扩展车种类时,只需要根据根据Car和CarFactory接口实现各自的车和各自工厂,不需要修改原代码,实现了动态扩展。
public class Consumer {
public static void main(String[] args) {
Car car1 = new TelsaFactory().getCar();
Car car2 = new FerrariFactory().getCar();
}
}
public interface CarFactory {
Car getCar();
}
public class FerrariFactory implements CarFactory {
@Override
public Car getCar() {
return new Ferrari();
}
}
public class TelsaFactory implements CarFactory{
@Override
public Car getCar() {
return new Tesla();
}
}
抽象工厂模式
当一个问题如上即涉及多个产品等级,且等级较为固定。
这里就放几个接口
public class Client {
public static void main(String[] args) {
System.out.println("============Ferrari==============");
ProductFactory ferrariFactory = new FerrariFactory();
Engine engine=ferrariFactory.produceEngine();
engine.power();
Wheel wheel=ferrariFactory.produceWheel();
wheel.materia();
wheel.size();
System.out.println("============Tesla==============");
ProductFactory teslaFactory=new TeslaFactory();
Engine engine1=teslaFactory.produceEngine();
engine1.power();
Wheel wheel1=teslaFactory.produceWheel();
wheel1.materia();
wheel1.size();
}
}
public interface Engine {
void power();
}
public interface Wheel {
void materia();
void size();
}
//抽象产品工厂
public interface ProductFactory {
// 生产发动机
Engine produceEngine();
// 生产轮胎
Wheel produceWheel();
}
原型模式
克隆模式即复制粘贴,可直接由Cloneable接口的native方法clone()实现
但原本的clone()由底层实现所以只是浅复制,要想实现深度复制需修改clone()代码。
一般工厂模式可与克隆模式结合。
import java.util.Date;
public class Prototype implements Cloneable{
private String name;
private Date date;
@Override
protected Object clone() throws CloneNotSupportedException {
// 浅复制
return super.clone();
// 深度复制
// Object obj=super.clone();
// Prototype temp=(Prototype) obj;
// temp.date=(Date)this.date.clone();
// return obj;
}
public Prototype(String name,Date date) {
this.name = name;
this.date = date;
}
@Override
public String toString() {
return "Prototype{" +
"name='" + name + '\'' +
", date=" + date +
'}';
}
public static void main(String[] args) throws CloneNotSupportedException{
Date date=new Date();
Prototype prototype1=new Prototype("我是名字",date);
Prototype prototype2=(Prototype)prototype1.clone();
// 由hashCode可以得出两者完全一样
System.out.println("prototype1->"+prototype1+" hashCode->"+prototype1.hashCode());
System.out.println("prototype2->"+prototype2+" hashCode->"+prototype2.hashCode());
}
}