Պարտականությունների շղթա (նախագծման ձևանմուշ)

Պարտականությունների շղթա (անգլ.՝ Chain of responsibility), վարքագծային նախագծման ձևանմուշ, որը նախատեսված է համակարգում պատասխանատվությունների բաշխումը իրականացնելու համար։

Պարտականությունների շղթա
ՏեսակՎարքագծային
Նշանակությունհամակարգում պատասխանատվությունների բաշխումը իրականացնելու համար
Նկարագրությունը ԳօՖի
"Design Patterns" գրքում
Այո

Ընդհանուր հասկացողություններ խմբագրել

  • Client - հայցող
  • Instance - նմուշ
  • Implementation - իրականացում
  • Product - արգասիք

Կիրառություն խմբագրել

Ձևանմուշը խորհուրդ է տրվում օգտագործել, երբ.

  • մշակվող համակարգում կա օբյեկտների խումբ, որոնք մշակում են հատուկ տիպի հաղորդագրություններ
  • բոլոր հաղորդագրությունները պետք է մշակվեն համակարգի գոնե մեկ օբյեկտի կողմից
  • համակարգում հաղորդագրությունները մշակվում են հետևյալ տրամաբանությամբ. «մշակիր ինքդ կամ ուղարկիր մյուսին»։ Այսինքն հաղորդագրություններից ոմանք մշակվում են այն մակարդակում, որտեղ որ ստացվել են, իսկ մյուսներն ուղարկվում են մյուս մակարդակի օբյեկտներին։

Օրինակներ խմբագրել

C++ խմբագրել

#include <iostream>
/*Неверный шаблон, это пример шаблона "Посредник"*/
class Colleague;

class Mediator
{
public:
	virtual void Send(std::string message, Colleague *colleague)=0;
        virtual ~Mediator(){}
};

class Colleague
{
protected:
	Mediator *mediator;
public:
	Colleague(Mediator *mediator)
	{
		this->mediator=mediator;
	}
        virtual ~Colleague(){}
};

class ConcreteColleague1:public Colleague
{
public:
	ConcreteColleague1(Mediator *mediator):Colleague(mediator)
	{
	}

	void Send(std::string message)
	{
		mediator->Send(message, this);
	}

	void Notify(std::string message)
	{
		std::cout << "Colleague1 gets message " << message.c_str() << std::endl;
	}
};

class ConcreteColleague2:public Colleague
{
public:
	ConcreteColleague2(Mediator *mediator):Colleague(mediator)
	{
	}

	void Send(std::string message)
	{
		mediator->Send(message, this);
	}

	void Notify(std::string message)
	{
		std::cout << "Colleague2 gets message " << message.c_str() << std::endl;
	}
};

class ConcreteMediator:public Mediator
{
protected:
	ConcreteColleague1	*m_Colleague1;
	ConcreteColleague2	*m_Colleague2;
public:
	void SetColleague1(ConcreteColleague1 *c)
	{
		m_Colleague1=c;
	}

	void SetColleague2(ConcreteColleague2 *c)
	{
		m_Colleague2=c;
	}

	virtual void Send(std::string message, Colleague *colleague)
	{
		if (colleague==static_cast<Colleague*>(m_Colleague1))
		{
			m_Colleague2->Notify(message);
		}
		else if (colleague==static_cast<Colleague*>(m_Colleague2))
		{
			m_Colleague1->Notify(message);
		}
	}
};

int main(int argc, char **argv)
{
	ConcreteMediator *m = new ConcreteMediator();

	ConcreteColleague1 *c1 = new ConcreteColleague1(m);
	ConcreteColleague2 *c2 = new ConcreteColleague2(m);

	m->SetColleague1(c1);
	m->SetColleague2(c2);

	c1->Send("How are you?");
	c2->Send("Fine, thanks");

	std::cin.get();
	return 0;
}

Output
Colleague2 gеts message How are you?
Colleague1 gеts message Fine, thanks

C# խմբագրել

// Chain of Responsibility pattern -- Structural example

using System;
 
namespace DoFactory.GangOfFour.Chain.Structural
{
  /// <summary>
  /// MainApp startup class for Structural
  /// Chain of Responsibility Design Pattern.
  /// </summary>
  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
      // Setup Chain of Responsibility
      Handler h1 = new ConcreteHandler1();
      Handler h2 = new ConcreteHandler2();
      Handler h3 = new ConcreteHandler3();
      h1.SetSuccessor(h2);
      h2.SetSuccessor(h3);
 
      // Generate and process request
      int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
 
      foreach (int request in requests)
      {
        h1.HandleRequest(request);
      }
 
      // Wait for user
      Console.ReadKey();
    }
  }
 
  /// <summary>
  /// The 'Handler' abstract class
  /// </summary>
  abstract class Handler
  {
    protected Handler successor;
 
    public void SetSuccessor(Handler successor)
    {
      this.successor = successor;
    }
 
    public abstract void HandleRequest(int request);
  }
 
  /// <summary>
  /// The 'ConcreteHandler1' class
  /// </summary>
  class ConcreteHandler1 : Handler
  {
    public override void HandleRequest(int request)
    {
      if (request >= 0 && request < 10)
      {
        Console.WriteLine("{0} handled request {1}",
          this.GetType().Name, request);
      }
      else if (successor != null)
      {
        successor.HandleRequest(request);
      }
    }
  }
 
  /// <summary>
  /// The 'ConcreteHandler2' class
  /// </summary>
  class ConcreteHandler2 : Handler
  {
    public override void HandleRequest(int request)
    {
      if (request >= 10 && request < 20)
      {
        Console.WriteLine("{0} handled request {1}",
          this.GetType().Name, request);
      }
      else if (successor != null)
      {
        successor.HandleRequest(request);
      }
    }
  }
 
  /// <summary>
  /// The 'ConcreteHandler3' class
  /// </summary>
  class ConcreteHandler3 : Handler
  {
    public override void HandleRequest(int request)
    {
      if (request >= 20 && request < 30)
      {
        Console.WriteLine("{0} handled request {1}",
          this.GetType().Name, request);
      }
      else if (successor != null)
      {
        successor.HandleRequest(request);
      }
    }
  }
}

Output
ConcreteHandler1 handled request 2
ConcreteHandler1 handled request 5
ConcreteHandler2 handled request 14
ConcreteHandler3 handled request 22
ConcreteHandler2 handled request 18
ConcreteHandler1 handled request 3
ConcreteHandler3 handled request 27
ConcreteHandler3 handled request 20

Java խմբագրել

{{Hider_hiding | title = Исходный текст на Java | content-style = text-align։ left; | content =

package chainofresp;
 
abstract class Logger {
    public static int ERR = 3;
    public static int NOTICE = 5;
    public static int DEBUG = 7;
    protected int mask;
 
    // The next element in the chain of responsibility
    protected Logger next;
 
    public Logger setNext(Logger log) {
        next = log;
        return log;
    }
 
    public void message(String msg, int priority) {
        if (priority <= mask) {
            writeMessage(msg);
        }
        if (next != null) {
            next.message(msg, priority);
        }
    }
 
    abstract protected void writeMessage(String msg);
}
 
class StdoutLogger extends Logger {
    public StdoutLogger(int mask) { 
        this.mask = mask;
    }
 
    protected void writeMessage(String msg) {
        System.out.println("Writing to stdout: " + msg);
    }
}
 
 
class EmailLogger extends Logger {
    public EmailLogger(int mask) {
        this.mask = mask;
    }
 
    protected void writeMessage(String msg) {
        System.out.println("Sending via email: " + msg);
    }
}
 
class StderrLogger extends Logger {
    public StderrLogger(int mask) {
        this.mask = mask;
    }
 
    protected void writeMessage(String msg) {
        System.out.println("Sending to stderr: " + msg);
    }
}
 
public class ChainOfResponsibilityExample {
    public static void main(String[] args) {
        // Build the chain of responsibility
        Logger logger, logger1,logger2;
        logger = new StdoutLogger(Logger.DEBUG);
        logger1 = logger.setNext(new EmailLogger(Logger.NOTICE));
        logger2 = logger1.setNext(new StderrLogger(Logger.ERR));
 
        // Handled by StdoutLogger
        logger.message("Entering function y.", Logger.DEBUG);
 
        // Handled by StdoutLogger and EmailLogger
        logger.message("Step1 completed.", Logger.NOTICE);
 
        // Handled by all three loggers
        logger.message("An error has occurred.", Logger.ERR);
    }
}
/*
The output is:
   Writing to stdout:   Entering function y.
   Writing to stdout:   Step1 completed.
   Sending via e-mail:  Step1 completed.
   Writing to stdout:   An error has occurred.
   Sending via e-mail:  An error has occurred.
   Writing to stderr:   An error has occurred.
*/