目录
一、定义
二、特点
三、优点
四、缺点
五、实例
六.涉及到的知识点
1、一个类里面有哪些东西?
2、类和实例
什么是类?
什么是实例?
什么是实例化?
3、字段和属性
什么是字段?
属性是什么?
属性怎么用呢?
属性有什么作用?
静态属性是什么?
属性和字段的公有部分解释:
4、修饰符
5、访问修饰符有哪些?
6、this关键字传递的是什么?
this关键字和对象之间有什么关系?
如果省略this会怎么样?
7、构造方法
8、方法重载
9、抽象类
什么是抽象类?
什么是重写?
10、switch....case多分支语句
if-else if与switch的比较
11、六大原则
12、六大关系
七、思维导图
一、定义
它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户
商场都有打折、返现活动—“满300减100”、“打五折”、“打八折”,我们可以根据自己花的钱数去选择对应的支付方式,这里的支付方式就可以理解为一种算法,算法本身只是一种策略。这些算法之间都可以相互替换。
二、特点
算法之间可以相互替换;
相同方式调用所有算法;
消除条件语句
三、优点
- 是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,他可以以相同的方式调用所有的算法,减少了各种算法与使用算法类之间的耦合
- 策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能
- 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试
- 每个算法可以保证他没有错误,修改其中任一个时也不会影响其他的算法、
- 当不同的行为堆砌在一个类中时,可以在使用这些行为的类中消除条件语句
- 策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性
四、缺点
- 策略模式造成很多的策略类,增加维护难度。
- 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类
五、实例
做一个商场收银软件,根据选择的收费方式(正常收费、打五折、打八折……)去计算客户所花的钱数(单价、数量)
现金收费抽象类
abstract class CashSuper
{
public abstract double acceptCash(double money);
}
正常收费子类
class CashNormal : CashSuper
{
public override double acceptCash(double money) //正常收费,原价返回
{
return money;
}
}
打折收费子类
class CashRebate : CashSuper
{
private double moneyRebate = 1d; //私有变量,钱数
public CashRebate(string moneyRebate) //构造方法
{
//ToDo:double.Parse():把括号里面string内容转换为double类型
//#中double.TryParse方法和double.Parse方法的异同之处:
//https://www.cnblogs.com/xu-yi/p/11178601.html
this.moneyRebate = double.Parse(moneyRebate); //将钱数字符串转换为双精度类型
}
public override double acceptCash(double money) //重写抽象方法
{
return money * moneyRebate;
}
}
返利收费子类
class CashReturn : CashSuper
{
//返利收费,初始化时必须要输入返利条件和返利值,
//比如满200返100,则moneyCondition为300,moneyReturn为100
private double moneyCondition = 0.0d; //返利条件
private double moneyReturn = 0.0d; //返利值
public CashReturn(string moneyCondition, string moneyReturn) //构造方法,传的值转换为double双精度类型
{
this.moneyCondition = double.Parse(moneyCondition);
this.moneyReturn = double.Parse(moneyReturn);
}
public override double acceptCash(double money) //重写抽象方法
{
double result = money; //定义一个变量,记录最后总计
if (money > moneyCondition) //判断,所花钱数是否>返利条件
result = money - Math.Floor(money / moneyCondition) * moneyReturn; //总计=花的钱-(花的钱/返利条件)*返利值
return result; //返回最后钱数
}
}
现金收费工厂类
class CashFactory
{
public static CashSuper createcashAccept(string type)
{
CashSuper cs = null; //现金收费抽象类变量为空
switch (type) //根据选择条件返回相应的对象
{
case "正常收费":
cs = new CashNormal(); //实例化正常收费子类
break;
case "满300返100":
CashReturn cr1 = new CashReturn("300", "100"); //实例化返利收费子类
cs = cr1; //赋值
break;
case "打8折":
CashRebate cr2 = new CashRebate("0.8"); //实例化打折收费子类
cs = cr2; //赋值
break;
}
return cs;
}
}
客户端代码
private void button1_Click(object sender, EventArgs e)
{
//Combox.SelectedItem:获取下拉框所选中的项
//Combox.SelectedIndex:获取下拉框选中项的索引
CashSuper csuper = CashFactory.createcashAccept(cbxType.SelectedItem.ToString());
totalPrices = csuper.acceptCash(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNumber.Text));
total = total + totalPrices; //总计=上次的总计钱数+最新一次的钱数
listBox1.Items.Add("单价:" + txtPrice.Text + " " //下拉框显示清单,通过多态,可以得到收取费用的结果
+ "数量:" + txtNumber.Text + " " +
"合计:" + totalPrices.ToString());
label4.Text = total.ToString(); //label显示钱数
}
六.涉及到的知识点
1、一个类里面有哪些东西?
2、类和实例
什么是类?
就是具有相同的属性和功能的对象的抽象的集合。注意:
- 类名称首字母大写。多个单词则各个首字母大写;
- 对外公开的方法需要用‘public’修饰符。
什么是实例?
就是一个真实的对象。比如我们都是‘人’,而你和我其实就是‘人’类的实例了。
什么是实例化?
创建对象的过程,使用new关键字来创建。
Cat cat = new Cat(); //其实做了两件事情
Cat cat; //第一步、声明一个Cat的对象,对象名为cat
cat = new Cat(); //第二步、将此cat对象实例化
3、字段和属性
什么是字段?
是存储类要满足其设计所需要的数据,字段是与类相关的变量。
private string name = ""; //name就是一个字段,私有的类变量
注意:
- 如果在定义字段时,在字段的类型前面使用了readonly关键字,那么字段就为只读字段,它只能在以下两个位置被赋值或者传递到方法中被改变。
- 在定义字段时赋值;
- 在类的构造函数内被赋值,或传递到方法中被改变,而且在构造函数中可以被多次赋值。
属性是什么?
是一个方法或一对方法体。提供对类或对象的访问。
属性怎么用呢?
它有两个方法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类即可直接对属性赋值
}
属性和字段的公有部分解释:
内存:
- 字段:分配内存
- 属性:不分配内存
命名规范:
- 字段:Camel大小写
- 属性:Pascal小写
4、修饰符
在变量前面可以加上访问修饰符(readonly、static)
readonly(只读):读取该字段的值不能给字段赋值
static:静态字段,可以直接通过类名访问该字段
5、访问修饰符有哪些?
- public:公有的,对任何类可访问
- private:私有的,只在类的内部可以访问,成员默认是这个
- protected:保护的,只允许该类的派生类访问
- internal:内部的,同一项目所有类可访问
6、this关键字传递的是什么?
- 用于区分类的成员和本地变量或参数;
- 作为调用方法的实参
//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关键字和对象之间有什么关系?
this引用的就是本类的一个对象。
如果省略this会怎么样?
直接写成name=name,只是把形参name赋值给参数变量本身而已,成员变量name的值没有改变
7、构造方法
- 什么时候用?就是对类进行初始化(在创建该类的对象时就会调用)。
- 有哪些特点?与类同名
无返回值
不需要void,在new时候调用
//希望每个小猫一诞生就有姓名
class Cat
{
private string name =""; //声明Cat类的私有字符串变量name
public Cat(string name) //定义Cat类的构造方法,参数是输入一个字符串
{
this.name =name; //将参数赋值给私有变量name
}
public string Shout()
{
return "我的名字叫"+name+" 喵";
}
}
注:所有类都有构造方法,如果你不编码则系统默认生成空的构造方法,若有定义的构造方法,那么默认的构造方法就会失效(这个构造方法什么也不做,只是为了让用户能够顺利地实例化)
8、方法重载
是什么?指方法名相同,但参数的数据类型、个数或顺序不同的方法。(一同二不同)
有什么好处?在不改变原方法的基础上,新增功能。
class Animal
{
private string name;
//方法重载:方法名相同、数据类型、个数/顺序不同
public Animal(){} //无参的构造方法
public Animal(string name) //有参的构造方法
{
this.name = name;
}
}
9、抽象类
什么是抽象类?
目的:抽取相同代码,实现封装思想
特点:
- 抽象类不能实例化;
- 抽象方法是必须被子类重写的方法;
- 如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其他一般方法
什么是重写?
将父类实现替换为它自己的实现
虚成员 | 抽象成员 | |
关键字 | virtual | abstract |
实现体 | 有实现体 | 没有实现体,被分号取代 |
在派生类中被覆写 | 可重写,也可不重写,使用override | 必须被重写,使用override |
10、switch....case多分支语句
什么时候使用switch语句?
当一个变量可能有多个值时
switch(表达式) { case 值 1: 语句块 1; break; case 值 2: 语句块 2; break; ... default: 语句块 n; break; } |
说明:
switch语句中表达式的结果必须是int、string、char、bool等数据类型;
如果switch语句中表达式的值与case后面的值相同,则执行相应的case后面的语句块;
case后面的值不能重复;
如果case语句为空,则可以不包含break
if-else if与switch的比较
相同点:都可以实现多分支结构
不同点:if-else if:可以处理范围
switch:一般只能用于等值比较
三者的区别:if有条件的执行一条语句
if-else有条件的执行一条或另一条语句
switch有条件的执行多条语句中的其中一条语句
11、六大原则
六大原则
12、六大关系
六大关系