每天两个设计模式(二)建造者模式、适配器模式

建造者模式

当我一看到这个模式的时候,一脸懵逼,然后去看代码,什么玩意这是。但是当你了解了其驱动背景,也就知道了建造者模式的爽。

建造模式的核心是为了分离对象的属性与创建过程,使用建造者模式创建出来的对象属性,被赋予了对应的值,换句话说,就是使用建造者模式,对应对象的属性要给一些默认值。建造者模式,用大白话说,我觉得就是** 适用于同一个对象在创建过程中有很多种组合这种 ** 。

与工厂模式的在实现方式上有所雷同,但是其内部含义是不一样的。可以理解为,使用建造者模式,就是跟对象属性初始化相关的,与普通方法类不同。
与工厂模式不同的是:
但相同的是他们最终的结果都是返回一个对象给客户端。

实现方式(一)

这个实现方式,与工厂模式类似,由中间商进行创建,看代码。

创建一个对象

上面也说了,建造者模式的背景是对对象属性的赋值,所以首先有一个对象,来创建人吧

public class Human {
	private String head;
	private String body;
	private String hand;
	private String foot;
	public String getHead() {
		return head;
	}
	public void setHead(String head) {
		this.head = head;
	}
	public String getBody() {
		return body;
	}
	public void setBody(String body) {
		this.body = body;
	}
	public String getHand() {
		return hand;
	}
	public void setHand(String hand) {
		this.hand = hand;
	}
	public String getFoot() {
		return foot;
	}
	public void setFoot(String foot) {
		this.foot = foot;
	}
}

接口

创建人的步骤,头、收、身体、脚、智商等,所以我们需要创建一个接口,来规定建造者的流程。

public interface IBuildHuman {
	public void buildHead();
	public void buildBody();
	public void buildHand();
	public void buildFoot();
	public Human createHuman();
}

创建具体实现者

public class Man implements IBuildHuman {
	
	Human human;
	
	public Man (){
		human = new Human();
	}
 
	@Override
	public void buildHead() {
		human.setHead("男人的头");		
	}
 
	@Override
	public void buildBody() {
		human.setBody("男人的身体");
		
	}
 
	@Override
	public void buildHand() {
		human.setHand("男人的手");		
	}
 
	@Override
	public void buildFoot() {
		human.setFoot("男人的脚");
		
	}
 
	@Override
	public Human createHuman() {
		return human;
	}    
}


public class WoMen implements IBuildHuman {
	
	Human human;
	
	public WoMen (){
		human = new Human();
	}
 
	@Override
	public void buildHead() {
		human.setHead("女人的头");		
	}
 
	@Override
	public void buildBody() {
		human.setBody("女人的身体");
		
	}
 
	@Override
	public void buildHand() {
		human.setHand("女人的手");		
	}
 
	@Override
	public void buildFoot() {
		human.setFoot("女人的脚");
		
	}
 
	@Override
	public Human createHuman() {
		return human;
	}    
}

创建director

director就是建造者模式的精髓,它是来执行我们刚才的造人动作的。没错,精髓就是我们刚才的造人动作,director的角色相当于工厂模式中的factory,但是具体实现还是不一样的,工厂模式中是根据参数进行创建对象并返回,而建造者模式的director,是在给对象的属性赋值并返回。


public class Director {
	public Human createHumanByDirecotr(IBuildHuman bh){
		bh.buildBody();
		bh.buildFoot();
		bh.buildHand();
		bh.buildHead();
		return bh.createHuman();
	}
}

//我们改一下,可以更加类似于工厂模式
public class Director {
	public Human createHumanByDirecotr(String param){
		IBuildHuman  bh;
		if(StringUtils.equals(param,"1")){
			bh = new Man();
		}else{
			bh = new WoMen();
		}
		//这样的话,我们就需要改一下接口实现类了,弄成模板方法(请自行实现),还要添加一个抽象类,个人感觉没必要!!
		return bh.createHuman();
	}
}

测试类

public class BuilderTest {
	public static void main(String[] args){
		Director director = new Director();
		Human human = director.createHumanByDirecotr(new Man());
		System.out.println(human.getHead());
		System.out.println(human.getBody());
		System.out.println(human.getHand());
		System.out.println(human.getFoot());
		Human human2 = director.createHumanByDirecotr(new WoMen());
		System.out.println(human2.getHead());
		System.out.println(human2.getBody());
		System.out.println(human2.getHand());
		System.out.println(human2.getFoot());
	} 	
}

实现方式二,去掉Director

需要最初对象的构造方法
需要一个建造类

public class HumanBuilder {

    // 男人、女人
    private String type;
    
    // 身材健壮or丰满
    private String shencai;
       
     //这个是建造者模式好像约定俗成的方法名,代表建造,里面把自身对象传给Human
    public Human Build () {
        Assert.assertNotNull(type);
        Assert.assertNotNull(shencai);
        
        return new Human(this);
    }

    public HumanBuilder type(String type) {
        this.type = type;
        return this;
    }

    public HumanBuilder shencai(String shencai) {
        this.shencai= shencai;
        return this;
    }
}
public class Human {
	private String head;
	private String body;
	private String hand;
	private String foot;
	public Human (HumanBuilder  hb){
		if(StringUtils.equals(hb.type,"1")){
			this.head="男人头";
			this.foot="男人脚";
			//。。。省略
		}else{
			this.body="女人身体";
			this.foot="女人脚";
			//。。。省略
		}

		if(StringUtils.equals(hb.shencai,"1")){
			this.head="强壮";
			//。。。省略
		}else{
			this.body="丰满";
			//。。。省略
		}
	}
	
	public String getHead() {
		return head;
	}
	public void setHead(String head) {
		this.head = head;
	}
	public String getBody() {
		return body;
	}
	public void setBody(String body) {
		this.body = body;
	}
	public String getHand() {
		return hand;
	}
	public void setHand(String hand) {
		this.hand = hand;
	}
	public String getFoot() {
		return foot;
	}
	public void setFoot(String foot) {
		this.foot = foot;
	}
}
@Test
public void test() {
    Human Human = new HumanBuilder().shencai("丰满").type("女人").build();
        
    System.out.println(JSON.toJSONString(car));
}

与工厂模式的不同与相同点

工厂模式中,关注的是对象的创建,并不关注对象的内容、属性,
而建造者模式,关注的则是对象中的属性赋值,两者侧重点不同。
而相同点则是,他们最终的结果,都是返回一个对象给客户端。

适配器模式

适配器模式,顾名思义,就是适配,那什么时候做适配呢,当然是被调用者,不能满足调用这所期待的样子,所以,我们需要在中间加一层适配。比如:
被调用者方法名是,sourceRequest()
调用者期待的方法名是hopeRequest()

如果不用适配器模式,那只能修改现有代码,如果sourceRequest方法或者hopeRequest方法都被很多方法调用,使用的地方都得要改成期望值,所以,不要修改。

分析适配器模式,我认为分析关键点应该站在调用者位置上,因为我们由现有的接口去适配它,所以我们需要一个与之相同的方法名,那有没有可以实现方法名一样,但是需要不能有具体的方法实现(因为具体实现,是需要调用被调用者的方法)----有,那就是接口、或者抽象类。但是由于java单继承的特性,所以在这个模式中接口类不能用抽象类来体现。

实现适配器有两种方式

类适配器

类适配器模式,就是在通过类继承的方式实现适配。
在这里插入图片描述

public interface AdacpterInterface {
    public void hopeRequest();
}


public class SourceRequest {
    public void sourceRequest(){
        System.out.println("sourceRequest");
    }
}

//因为类单继承的特性,所以类适配器模式下,hopeRequest方法定义所在的类不能用抽象类表示
public class AdapterRequest extends SourceRequest implements AdacpterInterface {
    @Override
    public void hopeRequest() {
        sourceRequest();
    }
}

对象适配器

方法适配器,就是在适配器中,持有需要适配的的对象,就是对象适配器模式
在这里插入图片描述

只需要该一下我们的适配器类就可以。

public class AdapterRequest2 implements AdacpterInterface{
    
    private SourceRequest sourceRequest;
    
    public AdapterRequest2(SourceRequest sourceRequest){
        this.sourceRequest = sourceRequest;
    }
    
    @Override
    public void hopeRequest() {
        sourceRequest.sourceRequest();
    }
}

如果我们接口方法是用抽象类表示的呢

public abstract class AdapterAbstract {
   public abstract void hopeRequest();
}


public class AdapterRequest3 extends AdapterAbstract{
    private SourceRequest sourceRequest;
    public AdapterRequest3(SourceRequest sourceRequest){
        this.sourceRequest = sourceRequest;
    }
    @Override
    public void hopeRequest() {
        sourceRequest.sourceRequest();
    }
}

也就是说当我们采用类适配器模式的时候,适配的接口不能用抽象类体现,而对象适配器可以使用。

适配器的优缺点

优点

  1. 复用。现有的类不符合系统的需要,通过适配器模式就可以让这些功能得到复用
  2. 解耦。引入适配类,无序修改原来的代码
  3. 扩展。在调用被适配接口前后,可以加入一些其他方法。(AOP思想)

缺点

缺点就是过多的使用适配器,会让人看起来非常混乱,比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,所以一般尽量不使用适配器,如果使用的地方多了,那么可以考虑一下重构了

不同模式的适配的优缺点

类适配器模式

继承方式,所以代码看起来简化,适配器类无需再设置额外的属性来引用被适配者的实例。

也是因为继承的方式,所以它是静态的定义方式,在灵活性上比较低,耦合度较高

对象适配器模式

对象引用的方式,是动态组合方式,也就是灵活性高,低耦合

对应的就要额外设置一个属性,来引用实例,较之复杂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值