Java设计模式(三)原型模式 适配器模式

(五)原型模式 Prototype

原型模式目的是复制一个现有对象来生成新的对象,而不是通过实例化的方式。原型模式需要实现 Cloneable 接口,覆写clone方法,复制分为浅复制、深复制。

浅复制:将一个对象复制后,基本数据类型的变量都重新创建,引用类型,指向的还是原对象所指向的。

深复制:讲一个对象复制后,不论基本数据类型和引用类型,都是重新创建,是完全的彻底的复制。

public class ProtoType {
	public static void main(String[] args) throws Exception {
		Father f=new Father();
		User u1=new User("123456",f);
		User u2=(User)u1.clone();
		User u3=(User) u1.shallowClone();
		System.out.println(u1==u2);		//false
		System.out.println(u1.f==u2.f);		//false
		System.out.println(u1.password == u2.password);		//false
		System.out.println(u1.f==u3.f);		//true
		System.out.println(u1.password == u3.password);		//true
	}
}
class User implements Cloneable,Serializable{
	String password;
	Father f;
	public User(String password,Father f){
		this.password=password;
		this.f=f;
	}
	//浅复制
	public Object shallowClone() throws CloneNotSupportedException{
		User user = (User)super.clone();
		return user;
		
	}
	//深复制
	public Object clone() throws CloneNotSupportedException {
		//return super.clone();
		ObjectOutputStream out=null;
		ObjectInputStream in=null;
		try {
			ByteArrayOutputStream bo = new ByteArrayOutputStream();
			out = new ObjectOutputStream(bo);
			out.writeObject(this);
			out.flush();
			byte[] bs = bo.toByteArray();
			ByteArrayInputStream bi = new ByteArrayInputStream(bs);
			in = new ObjectInputStream(bi);
			Object o = in.readObject();
			return o;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			return null;
		}
		finally{
			try {
				out.close();
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
class Father implements Serializable{}
原型模式与调用构造函数相比,复制创建的新对象会包含原始对象的某些状态,尤其当多个对象的类在属性上存在细微差别,方法完全相同时候。

浅复制与深复制还存在一个问题就是引用类型成本的问题。对于代码来说就是 Father 值的问题,上面的代码修改下。

class Father implements Serializable{
	String name = "father";
}
public static void main(String[] args) throws Exception {
		Father f = new Father();
		User u1 = new User("123456",f);
		User u2 = (User)u1.clone();
		User u3 = (User) u1.shallowClone();
		u1.f.name = "aaaa";
		System.out.println(u1.f.name);	//aaaa 原型
		System.out.println(u2.f.name);	//father 深复制
		System.out.println(u3.f.name);	//aaaa 浅复制
	}
这样应该能跟深刻的理解了。

(六)适配器模式

适配器的意义在于,使用不同接口的类所提供的服务为客户端提供它所期望的接口。原类型不做任何改变,用一个适配器把一个接口转成另一个接口,扩展了新的接口。适配器是面向对象的精髓。适配器模式主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

类的适配器模式:

Source类,拥有一个方法,待适配,目标接口 Targetable ,通过 Adapter 类将source的功能扩展到 targetable 。

class Source{
	public void method1(){
		System.out.println("this is original method!");
	}
}
interface Targetable{
	//原类中的方法
	public void method1();
	//新类中的方法
	public void method2();
}
class Adapter extends Source implements Targetable{
	//可以覆写Source的方法,也可以删去method1.会调用Source的
	public void method1() {
		super.method1();
		System.out.println("targetable method1");
	}
	public void method2() {
		System.out.println("targetable method2");
	}
}
public class AdapterTest {
	public static void main(String[] args) {
		Targetable target = new Adapter();
		target.method1();
		target.method2();
	}
}
对象的适配器模式:

跟类的适配器模式基本相同,只是不继承Source 类,持有Source类的实例。

class Adapter implements Targetable{// extends Source implements Targetable{
	private Source source;
	public Adapter(Source source){
		super();
		this.source = source;
	}
	//可以覆写Source的方法,也可以删去method1.会调用Source的
	public void method1() {
		source.method1();
		System.out.println("targetable method1");
	}
	public void method2() {
		System.out.println("targetable method2");
	}
}
public class AdapterTest {
	public static void main(String[] args) {
		Source source = new Source();
		Adapter target = new Adapter(source);
		target.method1();
		target.method2();
	}
}
接口适配器:

接口适配器跟前两种有点区别,一个接口会有多个抽象方法,我们写接口的实现类的时候,必须实现该接口所有的方法,但是并不是所有方法都是我们需要的,为了解决这个问题,我们引入了接口适配器。借助于一个抽象类,改抽象类实现了上面的接口,并实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系。我们最后写一个类,继承该抽象类,重写我们需要的方法。

interface Sourceable{
	public void method1();
	public void method2();
}
abstract class Wrapper implements Sourceable{
	//父类或者子类必须有一个实现method1 跟method2接口
	public void method1(){System.out.println("Wrapper method1");}
	public void method2(){System.out.println("Wrapper method2");}
}
class SourceSub1 extends Wrapper{
	//因为父类已经实现了method2所以不会报错
	public void method1(){
		System.out.println("SourceSub1");
	}
}
class SourceSub2 extends Wrapper{
	public void method2(){
		System.out.println("SourceSub2");
	}
}
public class AdapterInterface {
	public static void main(String[] args){
		SourceSub1 source1 = new SourceSub1();
		SourceSub2 source2 = new SourceSub2();
		source1.method1();	//SourceSub1
		source1.method2();	//Wrapper method2
		source2.method1();	//Wrapper method1
		source2.method2();	//SourceSub2
	}
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值