目录
思维导图
什么是职责链模式?
有什么优点呢?
有什么缺点呢?
什么场景使用呢?
代码展示
①、职责链模式
②、加薪代码重构
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
我要请假一个月,我发送审批给纪委,但是纪委只能批两小时以内的假,没有权限批假一个月,就需要转交给纪老师,纪老师也没有权限批假一个月,就转交给米老师,这时米老师说“好,准假了”。
这里一层一层的审批就像一条职责链,一个链条,逐层转交自己的请求。
Handler:定义一个处理请示的接口。
ConcreteHandler1:具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理它,否则就将该请求转发给它的后继者。
场景:
Handler类,定义一个处理请示的接口
abstract class Handler
{
protected Handler successor;
public void SetSuccessor(Handler successor) //设置继任者
{
this.successor = successor;
}
public abstract void HandleRequest(int request); //处理请求的抽象方法
}
ConcreteHandler1类,具体处理者类
class ConcreteHandler1 : Handler
{
public override void HandleRequest (int request)
{
if(request >=0 && request < 10) //0到10,处理此请求
{
Console.WriteLine("{0} 处理请求 {1}", this.GetType().Name, request);
}else if(successor != null)
{
successor.HandleRequest(request); //转移到下一位
}
}
}
ConcreteHandler2类
class ConcreteHandler2 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 10 && request < 20) //0到10,处理此请求
{
Console.WriteLine("{0} 处理请求 {1}", this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request); //转移到下一位
}
}
}
客户端代码
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2); //设置职责链的上家与下家
h2.SetSuccessor(h3);
int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
foreach (int request in requests) //循环给最小处理者提交请求,不同的数额,有不同权限处理者处理
{
h1.HandleRequest(request);
}
Console.ReadKey();
Request类,申请
class Request
{
//申请类别
private string requestType;
public string RequestType
{
get { return requestType; }
set { requestType = value; }
}
//申请内容
private string requestContent;
public string RequestContent
{
get { return requestContent; }
set { requestContent = value; }
}
//数量
private int number;
public int Number
{
get { return number; }
set { number = value; }
}
}
Manager类,管理者
abstract class Manager
{
protected string name;
//管理者的上级
protected Manager superior;
public Manager(string name)
{
this.name = name;
}
//设置管理者的上级
public void SetSuperior(Manager superior)
{
this.superior = superior;
}
//申请请求
abstract public void RequestApplications(Request request);
}
CommonManager类,经理
class CommonManager : Manager
{
public CommonManager(string name) : base(name) { }
public override void RequestApplications(Request request)
{
if (request.RequestType == "请假" && request.Number <= 2)
{
Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);
}
else
{
if (superior != null)
{
superior.RequestApplications(request);
}
}
}
}
Majordomo类,总监
class Majordomo : Manager
{
public Majordomo(string name) : base(name) { }
public override void RequestApplications(Request request)
{
if (request.RequestType == "请假" && request.Number <= 5)
{
Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);
}
else
{
if (superior != null)
{
superior.RequestApplications(request);
}
}
}
}
GeneralManager类,总经理
class GeneralManager : Manager
{
public GeneralManager(string name) : base(name) { }
public override void RequestApplications(Request request)
{
if (request.RequestType == "请假" && request.Number <= 5)
{
Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);
}
else if (request.RequestType == "加薪" && request.Number <= 500)
{
Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);
}
else if (request.RequestType == "加薪" && request.Number > 500)
{
Console.WriteLine("{0}:{1} 数量{2} 再说吧", name, request.RequestContent, request.Number);
}
}
}
客户端代码
CommonManager jinli = new CommonManager("金利");
Majordomo zongjian = new Majordomo("宗剑");
GeneralManager zhongjingli = new GeneralManager("钟精励");
jinli.SetSuperior(zongjian);
zongjian.SetSuperior(zhongjingli);
Request request = new Request();
request.RequestType = "请假";
request.RequestContent="小菜请假";
request.Number = 1;
jinli.RequestApplications(request);
Request request2 = new Request();
request2.RequestType = "请假";
request2.RequestContent = "小菜请假";
request2.Number = 4;
jinli.RequestApplications(request2);
Request request3 = new Request();
request3.RequestType = "加薪";
request3.RequestContent = "小菜请求加薪";
request3.Number = 500;
jinli.RequestApplications(request3);
Request request4 = new Request();
request4.RequestType = "加薪";
request4.RequestContent = "小菜请求加薪";
request4.Number = 1000;
jinli.RequestApplications(request4);
Console.ReadKey();
就是具有相同的属性和功能的对象的抽象的集合。注意:
就是一个真实的对象。比如我们都是‘人’,而你和我其实就是‘人’类的实例了。
创建对象的过程,使用new关键字来创建。
Cat cat = new Cat(); //其实做了两件事情
Cat cat; //第一步、声明一个Cat的对象,对象名为cat
cat = new Cat(); //第二步、将此cat对象实例化
是存储类要满足其设计所需要的数据,字段是与类相关的变量。
private string name = ""; //name就是一个字段,私有的类变量
注意:
是一个方法或一对方法体。提供对类或对象的访问。
它有两个方法get和set。
get访问器:从属性获取值。返回与声明的属性相同的数据类型,表示的意思是调用时可以得到内部字段的值或引用;
set访问器:为属性赋值。没有显式设置参数,但它有一个隐式参数,用关键字value表示,它的作用是调用属性时可以给内部的字段或引用赋值。
限制外部类对类中成员的访问权限,定义在类级别上。
private int _age; //年龄
public int Age
{
get //也可以直接在属性中进行判断操作、设置限制
{
if (_age >= 0 && _age <= 150) //如果年龄大于 0并且小于150的,(表示输入正确)
{
return _age; //则返回输入的年龄
}
else //否则,(表示输入错误)
{
return 18; //返回指定年龄18
}
}
set { _age = value; }
}
在属性前面加static关键字,这个属性就成为了静态属性。
有什么作用呢?
class Person
{
private static string name; //字段
public static string Name //属性
{
get { return name; }
set { name = value; }
}
}
static void Main(string[] args)
{
Person.Name = "小菜"; //不需要实例化Person类即可直接对属性赋值
}
内存:
命名规范:
在变量前面可以加上访问修饰符(readonly、static)
readonly(只读):读取该字段的值不能给字段赋值
static:静态字段,可以直接通过类名访问该字段
//this调用成员变量或成员方法
class Person
{
private string name; //字段
public void setName(string name) //方法
{
this.name = name; //将参数值赋予类中的成员变量
}
//成员变量和setName()方法中的形式参数的名称相同,都为name,那么如何区分使用的是哪一个变量呢?
//使用this关键字代表本类对象的引用,this.name指Person类中name成员变量,等号后面的name指传过来的形参name
}
this作为方法的返回值
public Book getBook()
{
return this; //返回Book类引用
}
在getBook()类中,方法的返回值为Book类,所以方法体中使用return this这种形式将Book类的对象返回
this引用的就是本类的一个对象。
直接写成name=name,只是把形参name赋值给参数变量本身而已,成员变量name的值没有改变
无返回值
不需要void,在new时候调用
//希望每个小猫一诞生就有姓名
class Cat
{
private string name =""; //声明Cat类的私有字符串变量name
public Cat(string name) //定义Cat类的构造方法,参数是输入一个字符串
{
this.name =name; //将参数赋值给私有变量name
}
public string Shout()
{
return "我的名字叫"+name+" 喵";
}
}
注:所有类都有构造方法,如果你不编码则系统默认生成空的构造方法,若有定义的构造方法,那么默认的构造方法就会失效(这个构造方法什么也不做,只是为了让用户能够顺利地实例化)
是什么?指方法名相同,但参数的数据类型、个数或顺序不同的方法。(一同二不同)
有什么好处?在不改变原方法的基础上,新增功能。
class Animal
{
private string name;
//方法重载:方法名相同、数据类型、个数/顺序不同
public Animal(){} //无参的构造方法
public Animal(string name) //有参的构造方法
{
this.name = name;
}
}
目的:抽取相同代码,实现封装思想
特点:
将父类实现替换为它自己的实现
虚成员 |
抽象成员 |
|
关键字 |
virtual |
abstract |
实现体 |
有实现体 |
没有实现体,被分号取代 |
在派生类中被覆写 |
可重写,也可不重写,使用override |
必须被重写,使用override |
六大原则
六大关系