【问题标题】:C# strategy and observer pattern codeC# 策略和观察者模式代码
【发布时间】:2013-05-07 12:57:06
【问题描述】:

您好,我正在尝试创建抽象类 Person 和两个子类 Student 和 Staff。 Person 类也有一个由 Practical 类通知的观察者。但学生只会收到有关更改的问题编号和有关学生感觉良好因素的工作人员的通知。任何学生都可以随时标记该因素。我已经设法让观察者工作,但仅限于 Person 类。我知道我必须将其抽象化,然后创建 Staff 和 Student 类,但我无法理解它。任何帮助都会很棒。谢谢 代码如下:

namespace ConsoleApplication1
{
class Practical : IPractical    //Practical class
{
    private String QuestionNumber;// the state which observers are interested in.
    private String Factor;
    private ArrayList observers;    // the collection of observers attached to this subject.

    public Practical(String qnumber, String f)
    {
        QuestionNumber = qnumber;
        Factor = f;
        observers = new ArrayList();
    }

    public void AddObserver(IPerson o) { observers.Add(o); }
    public void RemoveObserver(IPerson o) { observers.Remove(o); }

    public void NotifyObserverQN()
    {
        foreach (IPerson o in observers) { o.Update(QuestionNumber); }
    }

    public void NotifyObserverFactor()
    {
        foreach (IPerson o in observers) { o.Update(Factor); }
    }

    public String QN
    {
        get { return QuestionNumber; }
        set
        {
            QuestionNumber = value;
            NotifyObserverQN();     //notify about new question
        }
    }

    public String Fc
    {
        get { return Factor; }
        set
        {
            Factor = value;
            NotifyObserverFactor();     //notify about new ffctor
        }
    }
   }

      interface IPractical  //IPractical interface
     {
           void AddObserver(IPerson o);
           void RemoveObserver(IPerson o);
           void NotifyObserverQN();
           void NotifyObserverFactor();
    }



  class Person : IPerson
   {

    private string id;
    public Person(string i) { id = i; }
    public void Update(Object o)     { Console.WriteLine(" {0} notified about {1} .", id, o.ToString()); }

}

  interface IPerson     //Observer interface
   {
      void Update(Object o);

    }



 class Observer
  {

    public static void Main()
    {
        Console.WriteLine("\n\nStart\n\n");
        Practical practical = new Practical("Question", "Factor");
        IPerson a, b, c;
        a = new Person(" Student_1 ");
        b = new Person(" Student_2 ");
        c = new Person(" Staff_1   ");

        practical.AddObserver(a);
        practical.AddObserver(b);
        practical.AddObserver(c);

        practical.QN = "Question 1";   // all students notifie about Question 1 
        practical.Fc = "Feel-Good";
        practical.QN = "Question 2";   // all students notifie about Question 2
        practical.Fc = "Feel-Bad";

        Console.WriteLine("\n\nEnd\n\n");
    }

   } 

 }

【问题讨论】:

    标签: c# observer-pattern strategy-pattern


    【解决方案1】:

    理想情况下,您需要一个显式转换来检查特定观察者的类型是 Student 还是 Staff。在这种情况下,您可以将您的通知方法概括如下,而不是编写两个通知方法。

        public void Notify()
        {
            foreach (IPerson o in observers)
            {
                if (IPerson is Student)
                    o.Update(QuestionNumber);// Student - question number 
                else
                    o.Update(Factor);//Staff -  feel-good factor
    
            }
        }
    

    根据在这种情况下继承如何工作的请求;

     public abstract class Person : IPerson
        {
            private string id;
            public Person(){}
            public Person(string i)
            {
                id = i;
            }
            public abstract void Update(Object o);
        }
        public class Student:Person
    {
        public Student(){}
        public Student(string i):base(i)
        {
        }
        public override void Update(object o)
        {
            //whatever you wanted to do with Student
        }
    }
    public class Staff : Person
    {
         public Staff(){}
         public Staff(string i)
             : base(i)
        {
        }
        public override void Update(object o)
        {
            //whatever you wanted to do with Staff
        }
    }    
        interface IPerson     //Observer interface
        {
            void Update(Object o);
    
        }
    

    【讨论】:

    • 是的,但那还没有到来.. 我的意思是目前我被困在“如何创建班级 Student:Person 和班级 Staff:Person”以及他们所有的覆盖方法等。这是有点结合两种模式:策略和观察者。
    • 我已经包含了您所要求的内容。希望对您有所帮助
    • 谢谢,我之前做过,但我得到了这个:错误无法创建抽象类或接口的实例 ConsoleApplication.Person ... 在这三行中:a = new Person(" Student_1 ") ; b = new Person("Student_2"); c = new Person(" Staff_1 "); ...这就是我完全迷失的地方..
    • 我尝试过类似的操作:a = new Student("Student1");但在这种情况下,我必须删除参数并将括号留空。但我需要为每个新创建的用户分配用户 ID..
    • 你不能创建抽象类型(Person)的实例。您必须通过创建学生或员工的路线。我还更新了采用默认构造函数和参数化构造函数的解决方案来支持你所说的。
    【解决方案2】:

    我想在 C# 中补充一点,我更喜欢通过事件来实现观察者。观察者不必知道谁在观察它们以及它们的类型,而是在被观察类中引发事件。在您的情况下,您将在 Practical 类中引发 QuestionChanged 和 FactorChanged 事件。当您创建观察者时,您将他们注册到您的教职员工和学生班级,他们将选择他们感兴趣的事件。这样,任何人都不必知道另一个是什么类型。

    类似这样的东西(伪代码,可能无法编译):

    public class Practical {
        ...
    public event EventHandler QNChanged;
    public event EventHandler FcChanged;
    public String QN
    {
        get { return QuestionNumber; }
        set
        {
            QuestionNumber = value;
            OnQNChanged();     //notify about new question
        }
    }
    
    public String Fc
    {
        get { return Factor; }
        set
        {
            Factor = value;
            OnFcChanged();     //notify about new ffctor
        }
    }
    
    protected void OnFcChanged(){
        if(this.FcChanged != null) {
             FcChanged(this, null);
        }
    }
    
    protected void OnQnChanged(){
        if(this.QnChanged != null) {
             QnChanged(this, null);
        }
    }
    ...
    }
    
    public class Student {
         public Student(Practical practical){
              practical.QnChanged += Update;
         }
    
         public void Update(object sender, EventArgs args){
              Practical practical = (Practical) sender;
              // do something with practical
         }
    }
    
    public class Staff{
         public Staff(Practical practical){
              practical.FnChanged += Update;
         }
    
         public void Update(object sender, EventArgs args){
              Practical practical = (Practical) sender;
              // do something with practical
         }
    }
    
    class Observer
    {
    
    public static void Main()
    {
        ....
        var practical = new Practical("Question", "Factor");
    
        var a = new Student(practical);
        var b = new Staff(practical);
    
        practical.QN = "Question 1";   // all students notified about Question 1 
        practical.Fc = "Feel-Good";
        practical.QN = "Question 2";   // all students notified about Question 2
        practical.Fc = "Feel-Bad";
        ....
    
      }
    
     } 
    

    注意:你不必在构造函数中包含被观察项,你也可以添加一个方法来注册它,如果你愿意,它只是让例子更简单。即,您的教职员工和学生可以实现此接口:

     public interface IPracticalObserver {
          void RegisterPractical(IPractical practical);
          void Update(object practical, EventArgs args);
     }
    

    【讨论】:

    • 不太确定它是如何工作的。我明白了,但无法编译它... FcChanged(new EventArgs(this, null); 实际上有两个错误:------- 'System.EventArgs' 不包含采用的构造函数2 个参数 ------ 和 ------ Delegate 'EventHandler' 不接受 1 个参数... QNChanged(new blah-blah) 也给出了两个错误..
    • 对不起,我写这个是为了说明这个想法,来自记忆;我想你可以纠正错误。我只是打错了论据,现在更正了。
    猜你喜欢
    • 2012-02-15
    • 2021-11-22
    • 2016-02-20
    • 2023-04-10
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多