2

ファクトリがオブジェクトに機能をパックできるようにする以下の例を作成しましたが、問題は機能がオブジェクトから切り離されていることです。

私の最終的な目標は、logsavedisplayなどのアタッチ機能で、それぞれの異なるオブジェクトが持つ特定のプロパティを操作することです。

オブジェクトのデータをデータベースに保存する「保存」や、そのアクティビティをログに記録する「ログ」などの機能を有効にしながら、この例の外観を装飾する側面を維持するにはどうすればよいでしょうか?

using System;
using System.Collections.Generic;

namespace FuncAdorn3923
{
    class Program
    {
        static void Main(string[] args)
        {

            Customer customer = new Customer();
            ObjectFactory.Instance.AdornFunctionality(customer, "add");
            Console.WriteLine(customer.CallAlgorithm("add", 64, 36));

            Employee employee = new Employee();
            ObjectFactory.Instance.AdornFunctionality(employee, "add");
            ObjectFactory.Instance.AdornFunctionality(employee, "subtract");
            Console.WriteLine(employee.CallAlgorithm("add", 5, 15));
            Console.WriteLine(employee.CallAlgorithm("subtract", 66, 16));

            Console.ReadLine();
        }
    }

    public class ObjectFactory
    {
        private static ObjectFactory singleton;

        public void AdornFunctionality(AdornedObject ao, string idCode)
        {
            Func<int, int, int> add = (i, j) => i + j;
            Func<int, int, int> subtract = (i, j) => i - j;

            switch (idCode)
            {
                case "add":
                    ao.LoadAlgorithm(idCode, add);
                    break;
                case "subtract":
                    ao.LoadAlgorithm(idCode, subtract);
                    break;
            }
        }

        public static ObjectFactory Instance
        {
            get
            {
                if (singleton == null)
                    singleton = new ObjectFactory();
                return singleton;
            }
        }

    }

    public abstract class AdornedObject
    {
        private Dictionary<string, Func<int, int, int>> algorithms = 
            new Dictionary<string, Func<int, int, int>>();

        public void LoadAlgorithm(string idCode, Func<int,int,int> func)
        {
            algorithms.Add(idCode, func);
        }

        public int CallAlgorithm(string idCode, int i1, int i2)
        {
            Func<int,int,int> func = algorithms[idCode];
            return func.Invoke(i1, i2);
        }
    }

    public class Customer : AdornedObject
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int NumberOfProductsBought { get; set; }
    }

    public class Employee : AdornedObject
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }

}
4

3 に答える 3

2

個人的には、ビジター パターンのような、より優れたデザイン パターンをお勧めしますが、型の安全性を捨てることでコードを機能させることができます。派生クラスでDelegateはなく使用し、次を使用します。FuncAction

    static void Main(string[] args)
    {

        Customer customer = new Customer();
        ObjectFactory.Instance.AdornFunctionality(customer, "add");
        Console.WriteLine(customer.CallAlgorithm("add", 64, 36));

        Employee employee = new Employee();
        ObjectFactory.Instance.AdornFunctionality(employee, "add");
        ObjectFactory.Instance.AdornFunctionality(employee, "subtract");
        ObjectFactory.Instance.AdornFunctionality(employee, "save");
        Console.WriteLine(employee.CallAlgorithm("add", 5, 15));
        Console.WriteLine(employee.CallAlgorithm("subtract", 66, 16));
        Console.WriteLine(employee.CallAlgorithm("save"));

        Console.ReadLine();
    }
}

public class ObjectFactory
{
    private static ObjectFactory singleton;

    public void AdornFunctionality(AdornedObject ao, string idCode)
    {
        Func<int, int, int> add = (i, j) => i + j;
        Func<int, int, int> subtract = (i, j) => i - j;
        Action save = () => Console.WriteLine("{0} has been saved", ao.ToString());

        switch (idCode)
        {
            case "add":
                ao.LoadAlgorithm(idCode, add);
                break;
            case "subtract":
                ao.LoadAlgorithm(idCode, subtract);
                break;
            case "save":
                ao.LoadAlgorithm(idCode, save);
                break;
        }
    }

    public static ObjectFactory Instance
    {
        get
        {
            if (singleton == null)
                singleton = new ObjectFactory();
            return singleton;
        }
    }

}

public abstract class AdornedObject
{
    private Dictionary<string, Delegate> algorithms = new Dictionary<string, Delegate>();

    public void LoadAlgorithm(string idCode, Delegate func)
    {
        algorithms.Add(idCode, func);
    }

    public object CallAlgorithm(string idCode, params object[] args)
    {
        Delegate func = algorithms[idCode];
        return func.DynamicInvoke(args);
    }
}
于 2009-10-08T14:57:44.637 に答える
1

これは、訪問者パターンの典型的なケースのように見えます。

アルゴリズム (訪問者) は、装飾する (または訪問する) オブジェクトに合わせて調整するか、少なくとも装飾されたオブジェクトが実装するインターフェイスに合わせて調整する必要があります。

たとえば、Employeeオブジェクトに次のようなメソッドがあるとします。

public class Employee: IEmployee {
    public void Accept(IEmployeeAlgorithm algorithm) {
        algorithm.Visit(this);
    }
}

IEmployeeAlgorithmオブジェクトは、これに似たインターフェイスを持ちます (これらは、必要に応じて簡単にAction<Employee>デリゲートにするか、他のシグネチャを使用できます)。

public interface IEmployeeAlgorithm {
    void Visit(IEmployee employee);
}

IDictionary<string, IEmployeeAlgorithm>最後に、アルゴリズムのキーを指定して動的に呼び出したい場合は、メンバーに格納することで、現在と同様の方法でそれを行うことができます。

于 2009-10-08T14:53:29.530 に答える
0

PostSharpプロジェクトをチェックアウトします。それらは、この種の関心の分離を可能にし、これを達成するためのいくつかの簡単な方法を可能にします。これらを使用すると、実行時にクラス/プロパティに追加されるコードを外部で定義できます。特定の要件(またはこの特定の例)についてはわかりませんが、確認する必要があります。

于 2009-10-08T14:53:53.990 に答える