23种设计模式之我见----结构型设计模式(2)

软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。

创建型模式由两个主导思想构成。一是将系统使用的具体类封装起来,二是隐藏这些具体类的实例创建和结合的方式。[1]

创建型模式又分为对象创建型模式和类创建型模式。对象创建型模式处理对象的创建,类创建型模式处理类的创建。详细地说,对象创建型模式把对象创建的一部分推迟到另一个对象中,而类创建型模式将它对象的创建推迟到子类中。[2]

6.适配器模式(Adapter)

顾名思义,适配器模式就是让那些原本由于接口不兼容而不能一起工作的那些类可以一起工作。 


其实就是利用adapter包装了一下而已,代码如下:

/// <summary>
    /// 定义客户端期待的接口
    /// </summary>
    public class Target
    {
        /// <summary>
        /// 使用virtual修饰以便子类可以重写
        /// </summary>
        public virtual void Request()
        {

System.out.println("This is a common request");

} } /// <summary> /// 定义需要适配的类 /// </summary> public class Adaptee { public void SpecificRequest() { System.out.println("This is a special request."); } } /// <summary> /// 定义适配器 /// </summary> public class Adapter implements Target { // 建立一个私有的Adeptee对象 private Adaptee adaptee = new Adaptee(); /// <summary> /// 通过重写,表面上调用Request()方法,变成了实际调用SpecificRequest() /// </summary> public override void Request() { adaptee.SpecificRequest(); } }


7.装饰模式()

装饰模式我想放到这里和适配器模式一起说,因为两者还是有一定的迷惑性:装饰模式是将一个对象包装成为有不同表现形式的对象的过程,比如商场里面同样是土豆,却会有薯条,薯片等不同的表现形式,而适配器只是某一个对象需要另外一个有不同接口的对象的功能,比如说薯条想让你吃起来不是薯条而是番茄的味道。



clip_image002

具体的实现为:

public class ConcreteComponent implements Component
{
	public void operation()
	{
		// Write your code here
	}
}
 

Decorator:

维持一个指向Component对象的引用,并定义一个与 Component接口一致的接口。

public class Decorator implements Component
{
	public Decorator(Component component)
	{
		this.component = component;
	}
	
	public void operation()
	{
		component.operation();
	}
	
	private Component component;
}
 

Concrete Decorator:

在Concrete Component的行为之前或之后,加上自己的行为,以“贴上”附加的职责。

public class ConcreteDecorator extends Decorator
{
	public void operation()
	{
		//addBehavior也可以在前面
		
		super.operation();
		
		addBehavior();
	}
	
	private void addBehavior()
	{
		//your code
	}
}

装饰模式的应用相当广泛,我们可以将之比对到spring的AOP,也是同样的原理,其在java/io中也是主要的使用模式:


clip_image008

仿照上面的java/io

我们在这里也写一个装饰类,将输入流的大写字母变成小写字母:

public class LowerCaseInputStream extends FilterInputStream{

	protected LowerCaseInputStream(InputStream in) {
		super(in);
		// TODO Auto-generated constructor stub
	}

	@Override
	public int read() throws IOException{
		int c = super.read();
		return (c==-1?c:Character.toLowerCase((char)c));
	}
	
	@Override
	public int read(byte[] b, int offset, int len) throws IOException
	{
		int result = super.read(b, offset, len);
		
		for (int i = offset; i < offset + result; i++)
		{
			b[i] = (byte) Character.toLowerCase((char) b[i]);
		}
		
		return result;
		
	}
	
}


测试类,随便找一个file

InputStream in = new LowerCaseInputStream(new BufferedInputStream(
					new FileInputStream("D:\\test.txt")));
//进行查看即可


8组合模式(Composite

这个模式我想详细的说一下,这是我原来面试碰到的一道题:

面试官首先是这么说的:如果让你设计现在操作系统的文件和文件夹,你会怎么设计?

我当时想到的是如何使用递归来解决这个问题,但是答得比较乱,因为在设计数据结构的时候我当时并没有一个很清晰的认识,后来面试官很和蔼的帮我很详细的分析了这个问题,并且让我去看一下组合模式,其实就是一年前。

其实我觉得如果稍微了解这个模式,就会觉得这个例子实在是太贴合不过了,这个模式就是这么使用的。

clip_image008


来说说Composite组合模式的几个要点:

       1、Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码可以一致的处理对象和对象容器,无需关心处理的是单个对象,还是组合的对象容器。

2、将“客户代码与复杂的对象容器结构”解耦是Composite模式的核心思想,解耦之后,客户代码将与纯粹的对象接口——而非对象容器的复杂内部实现结构——发生依赖关系,从而更能“应对变化”。

3、Composite模式中,是将“Add和Remove的和对象容器相关的方法”定义在“表示抽象对象的Component类”中,还是将其定义在“表示对象容器的Composite类”中,是一个关乎“透明性”和“安全性”的两难问题,需要仔细权衡结构,这又是必须付出的代价。

4、Composite模式在具体实现中,可以让父对象中的字对象反向追溯:如果父对象有频繁的遍历需求,可使用缓存技巧来改善效率


具体实现为:

基类

public abstract class Component {
	
	protected String name;
	
	public Component(String name){
		this.name = name;
	}
	
	public abstract void add(Component component);    //为树枝节点还有子节点
	public abstract void remove(Component component); //为树枝节点移除某个子节点
	public abstract void showComponent(int dept);   //显示该节点的树形结构
}

树枝类

import java.util.ArrayList;
import java.util.List;


public class Composite extends Component{
	
	private List<Component> children = new ArrayList<Component>();
	private String showDept = "";

	public Composite(String name) {
		super(name);
	}

	@Override
	public void add(Component component) {
		children.add(component);
	}

	@Override
	public void remove(Component component) {
		children.remove(component);
	}

	@Override
	public void showComponent(int dept) {
		for(int i=0;i<dept;i++){
			showDept += "--";
		}
		System.out.println(showDept+name);
		for(Component component : children){
			component.showComponent(dept + 1);
		}
	}
}

叶子类
public class Leaf extends Component{

	String showDept ="";
	public Leaf(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void add(Component component) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void remove(Component component) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void showComponent(int dept) {
		// TODO Auto-generated method stub
		for(int i=0;i<dept;i++){
			showDept += "--";
		}	
		System.out.println(showDept+name);
	}
}

测试类 client
public class TestCompositePattern {
	public static void main(String[] args){
		
		Composite root = new Composite("树根");
		
		Composite branch1 = new Composite("树枝一");
		Composite branch2 = new Composite("树枝二");		
		Composite branch21 = new Composite("树枝二子树枝一");
		
		branch1.add(new Leaf("树枝一叶子一"));
		branch1.add(new Leaf("树枝一叶子二"));
		branch1.add(new Leaf("树枝一叶子三"));
		branch21.add(new Leaf("树枝二子树枝一叶子一"));		
		branch2.add(branch21);
			
		root.add(branch1);
		root.add(branch2);
		root.showComponent(1);				
	}
}
结果为:
--树根
----树枝一
------树枝一叶子一
------树枝一叶子二
------树枝一叶子三
----树枝二
------树枝二子树枝一
--------树枝二子树枝一叶子一


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值