[Object-oriented] 介面、抽象類別的抽象合成

[Object-oriented] : 介面、抽象類別的合成

 

前言 :

 

物件導向設計守則裡有一條:多用合成,少用繼承。
物件導向設計守則的內容可以參考,
[深入淺出設計模式] : http://www.oreilly.com.tw/product_java.php?id=a163
本篇文章示範如何實作介面、抽象類別的抽象合成,讓合成之後的類別依然保有抽象方法。

 

使用時機 :

 

當有一堆抽象類別,想要集合成一個大的抽象類別時使用。
例如說
現在要實作Facade這個模式 可是有些抽象物件的方法,要讓使用者去實作。 這個時候,抽象合成就可以派上用場。

 

結構 :

 

 

實作 :

 

首先先要有一個抽象類別

public abstract class Strategy
{
    public int ClassMethod001(string x)
    {
        return int.Parse(x);
    }

    public abstract string ClassMethod002(int x);        
}

 

再來就是抽象類別的合成類別

 

public abstract class Context
{
    // Properties
    private Strategy _strategy = null;


    // Constructor
    public Context()
    {
        // Agent
        _strategy = new StrategyAgent(this.ClassMethod002);
    }


    // Methods
    public int ClassMethod001(string x)
    {
        return _strategy.ClassMethod001(x);
    }

    public abstract string ClassMethod002(int x);
        

    // Class
    private class StrategyAgent : Strategy
    {
        // Delegate
        public delegate string ClassMethod002Delegate(int x);


        // Properties
        private ClassMethod002Delegate _classMethod002Delegate = null;


        // Constructor
        public StrategyAgent(ClassMethod002Delegate classMethod002Delegate)
        {
            #region Require

            if (classMethod002Delegate == null) throw new ArgumentNullException();

            #endregion
            _classMethod002Delegate = classMethod002Delegate;
        }

        // Methods
        public override string ClassMethod002(int x)
        {
            return _classMethod002Delegate(x);
        }
    }
}

 

最後我們就可以繼承合成類別,來達成繼承被合成抽象類別的工作。

 

public class ContextA : Context
{
    public override string ClassMethod002(int x)
    {
        return x.ToString("D3");
    }
}

public class ContextB : Context
{
    public override string ClassMethod002(int x)
    {
        return x.ToString("X2");
    }
}

 

執行

 

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ContextA contextA = new ContextA();
            Console.WriteLine(contextA.ClassMethod001("255"));  
            Console.WriteLine(contextA.ClassMethod002(255));

            Console.WriteLine();

            ContextB contextB = new ContextB();
            Console.WriteLine(contextB.ClassMethod001("255"));     
            Console.WriteLine(contextB.ClassMethod002(0xFF));            

            Console.ReadLine();
        }
    }
}
期許自己
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。