面向对象
面向对象的好处:可维护,可复用,可扩展
三大特性:封装,继承和多态。
封装:把业务和界面分离。
继承和多态:降低程序的耦合(保护原先的程序,只需要对一部分进行修改,而不需要对全部进行修改。)
1.开放-封闭原则:软件实体(类,模块,函数等等)可以扩展,但是不可以修改。
2.单一原则:就一个类而言,应该仅有一个引起它变化的原因(每个类实现单一的功能)。
3.依赖倒转原则:针对接口或抽象类编程,不要针对实现编程(细节应该依赖于抽象)
4.里氏代换原则:子类必须能够能够替换掉它们的父类型,这样使得父类类型在无需修改的情况下就可以扩展。
设计模式分为3大类
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式;
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式;
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、访问者模式,中介者模式、解释器模式。
单例模式,只能创建一个对象
确保一个类只有一个实例,并提供一个访问本类实例唯一的全局访问点。单例模式的使用是当我们的系统中某个对象只需要一个实例的情况。
public class Singleton//单例模式
{
// 定义一个静态变量来保存类的实例
private static Singleton uniqueInstance;
//定义一个标识确保线程同步
private static readonly object locker = new object();
// 定义私有构造函数,使外界不能创建该类实例
private Singleton()
{ }
public static Singleton GetInstance()
{
// 当第一个线程运行到这里时,此时会对locker对象 "加锁",
// 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
// lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
// 双重锁定只需要一句判断就可以了
if (uniqueInstance == null)
{
lock(locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
为什么会有2个uniqueInstance?
当instance为null,并且同时有2个线程调用GetInstance()方法时,它们都将通过instance==null的判断。然后由于lock机制,这两个线程则只有一个进入,另一个在外面等待,必须要其中的一个进入并出来后,另一个才能进入。而此时如果没有第二重的instance是否为null的判断,则第一个线程创建了实例,而第二个线程还是可以继续再创建新的实例,这就没有达到单例的目的。
———————————————————————————————————————————
简单工厂模式,一个对象的创建
一个简单的工厂模式分别用到了封装,继承和多态,使程序容易维护,容易扩展,容易复用,提高灵活性。
使用封装将业务逻辑和界面逻辑分开;使用继承和多态降低耦合
在简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。缺点是违背了“开放-封闭”原则。
public abstract class MobilePhone1
{
public abstract void print();
}
public class Iphone1:MobilePhone1
{
public override void print()
{
Console.WriteLine("我是苹果手机");
}
}
public class XiaoMi1:MobilePhone1
{
public override void print()
{
Console.WriteLine("我是小米手机");
}
}
public class MobilePhoneFactory1
{
public static MobilePhone1 CreateMobilePhone(string phonebrand)
{
MobilePhone1 mobilePhone = null;
switch(phonebrand)
{
case"苹果":
mobilePhone = new Iphone1();break;
case"小米":
mobilePhone = new XiaoMi1();break;
default:
break;
}
return mobilePhone;
}
}
public class Operation
{
private double _numberA = 0;
private double _numberB = 0;
public double NumberA
{
get;
set;
}
public double NumberB
{
get;
set;
}
public virtual double GetResult()
{
double result = 0;
return result;
}
}
class OperationAdd:Operation
{
public override double GetResult()
{
double result = 0;
result = NumberA + NumberB;
return result;
}
}
class OperationSub : Operation
{
public override double GetResult()
{
double result = 0;
result = NumberA - NumberB;
return result;
}
}
//简单工厂模式,到底实例化谁,将来会不会增加实例化的对象
public class OperationFactory
{
public static Operation createOperate(string operate)
{
Operation oper = null;
switch(operate)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
}
return oper;
}
}
static void Main(string[] args)
{
Operation oper;
oper = OperationFactory.createOperate("+");
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult();
Console.WriteLine(result);
}
工厂方法模式(Factory Method)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延续到祺子类中。
参考:C#设计模式–工厂方法模式
工厂方法模式克服了简单工厂违背开放-封闭原则(软件实体应该可以扩展,但是不可以修改)的缺点,又保持了封装对象创建过程的优点。但缺点是每加一个产品,就需要加一个产品工厂的类,增加额外的开发。
public abstract class MobilePhone
{
public abstract void print();
}
public class Iphone:MobilePhone
{
public override void print()
{
Console.WriteLine("我是苹果手机!");
}
}
public class XiaoMi:MobilePhone
{
public override void print()
{
Console.WriteLine("我是小米手机");
}
}
public abstract class MobilePhoneFactory
{
public abstract MobilePhone Create();
}
public class IphoneFactory: MobilePhoneFactory
{
public override MobilePhone Create()
{
return new Iphone();
}
}
public class XiaoMiFactory : MobilePhoneFactory
{
public override MobilePhone Create()
{
return new XiaoMi();
}
}
工厂方法克服了简单工厂违背开发-封闭原则的缺点,又保持了封装对象创建过程的优点。
工厂方法模式是简单工厂的扩展,工厂方法把简单工厂的内部逻辑判断转移到了客户端进行,想要增加功能,以前是修改工厂类,现在是修改客户端。
依旧以计算器的例子为例,将在上面简单工厂的基础上进行修改
interface IFactory
{
Operation CreateOperation();
}
class AddFactory:IFactory
{
public Operation CreateOperation()
{
return new OperationAdd();
}
}
class DivFactory
{
public Operation CreateOperation()
{
return new OperationDiv();
}
}
客户端代码
IFactory operFactory = new AddFactory();//工厂方法模式
Operation oper = operFactory.CreateOperation();
oper.NumberA = 4;
oper.NumberB = 2;
double result = oper.GetResult();
Console.WriteLine(result);
Console.Read();
————————————————————————————————————————
抽象工厂模式(Abstract Factory),一组对象的创建
工厂方法模式每个具体工厂类只完成单个实例的创建,所以它具有很好的可扩展性。但是在实际的应用中,一个工厂不止会创建单一的产品,而是一系列的产品,这就引入了抽象工厂的概念。解决涉及多个产品系列的问题。
参考博客C#设计模式–抽象工厂模式,看一下UML
//抽象工厂类:提供创建不同品牌的手机屏幕和手机主板
public abstract class AbstractFactory
{
//工厂生产屏幕
public abstract Screen CreateScreen();
//工厂生产主板
public abstract MotherBoard CreateMotherBoard();
}
//屏幕抽象类:提供每一品牌的屏幕的继承
public abstract class Screen
{
public abstract void print();
}
/// 主板抽象类:提供每一品牌的主板的继承
/// </summary>
public abstract class MotherBoard
{
public abstract void print();
}
/// 苹果手机屏幕
public class AppleScreen : Screen
{
public override void print()
{
Console.WriteLine("苹果手机屏幕!");
}
}
/// 苹果手机主板
public class AppleMotherBoard : MotherBoard
{
public override void print()
{
Console.WriteLine("苹果手机主板!");
}
}
/// 小米手机屏幕
public class XiaoMiScreen : Screen
{
public override void print()
{
Console.WriteLine("小米手机屏幕!");
}
}
/// 小米手机主板类
public class XiaoMiMotherBoard : MotherBoard
{
public override void print()
{
Console.WriteLine("小米手机主板!");
}
}
/// 苹果手机工厂
public class AppleFactory : AbstractFactory
{
/// 生产苹果手机屏幕
public override Screen CreateScreen()
{
return new AppleScreen();
}
/// 生产苹果手机主板
public override MotherBoard CreateMotherBoard()
{
return new AppleMotherBoard();
}
}
建造者模式(Builder)
将一个复杂对象的构建与它的表示分开,使得同样的构建过程可以创建不同的表示。如果我们用了建造者模式,那么用户就只需要指定需要建造的类型就可以得到它们,而具体建造的过程和细节就不需要知道了。(过程是稳定的,但是具体的细节是不同的)
建造者模式中一个很重要的类,指挥者(Director),用它来控制建造过程,也用它来隔离用户和建造过程的关联。
abstract class PersonBuilder
{
//把过程稳定住
protected Graphics g;
protected Pen p;
public PersonBuilder(Graphics g,Pen p)
{
this.g = g;
this.p = p;
}
public abstract void BuildHead();
public abstract void BuildBody();
public abstract void BuildArmLeft();
public abstract void BuildArmRight();
public abstract void BuildLegLeft();
public abstract void BuildLegRight();
}
class PersonThinBuilder:PersonBuilder
{
//具体的细节
public PersonThinBuilder(Graphics g,Pen p) : base(g, p)//base用于在派生类中访问重写的基类成员,Base 是子类中引用父类
{
}
public override void BuildHead()
{
g.DrawEllipse(p, 50, 20, 30, 30);
}
public override void BuildBody()
{
g.DrawRectangle(p, 60, 50, 10, 50);
}
public override void BuildArmLeft()
{
g.DrawLine(p, 60, 50, 40, 100);
}
public override void BuildArmRight()
{
g.DrawLine(p, 70, 50, 90, 100);
}
public override void BuildLegLeft()
{
g.DrawLine(p, 60, 100, 45, 150);
}
public override void BuildLegRight()
{
g.DrawLine(p, 70, 100, 85, 150);
}
}
class PersonDirector
{
private PersonBuilder pb;
public PersonDirector(PersonBuilder pb)//用户告诉指挥者需要什么样的小人
{
this.pb = pb;
}
public void CreatePerson()
{
pb.BuildHead();
pb.BuildBody();
pb.BuildArmLeft();
pb.BuildArmRight();
pb.BuildLegLeft();
pb.BuildLegRight();
}
}