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);				
	}
}
結果爲:
--樹根
----樹枝一
------樹枝一葉子一
------樹枝一葉子二
------樹枝一葉子三
----樹枝二
------樹枝二子樹枝一
--------樹枝二子樹枝一葉子一


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章