1 创建型模式
确保对象的唯一性-单例模式
集中式工厂的实现-简单工厂模式
多台工厂的实现-工厂方法模式
产品族的创建-抽象工厂模式
对象的克隆-原型模式(注意深拷贝与浅拷贝)
复杂对象的组装与创建-建造者模式
1.1 单例模式
1.2 简单工厂模式
//首先,我们定义一个接口Animal:
public interface Animal {
void speak();
}
然后,我们创建两个实现了Animal接口的类Dog和Cat:
public class Dog implements Animal {
@Override
public void speak() {
System.out.println("Woof!");
}
}
public class Cat implements Animal {
@Override
public void speak() {
System.out.println("Meow!");
}
}
//接下来,我们创建一个名为AnimalFactory的工厂类,它可以根据传入的参数来创建并返回相应的动物对象:
public class AnimalFactory {
public Animal createAnimal(String type) {
if (type == null) {
return null;
}
if (type.equalsIgnoreCase("DOG")) {
return new Dog();
} else if (type.equalsIgnoreCase("CAT")) {
return new Cat();
}
return null;
}
}
//最后,我们在main方法中使用AnimalFactory来创建动物对象,并调用它们的speak方法:
public class Main {
public static void main(String[] args) {
AnimalFactory factory = new AnimalFactory();
Animal dog = factory.createAnimal("DOG");
if (dog != null) {
dog.speak();
}
Animal cat = factory.createAnimal("CAT");
if (cat != null) {
cat.speak();
}
}
}
1.3 工厂方法模式
工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。但缺点是由于每加一个产品,就需要加一个产品工厂的类,增加了额外的开发量。利用‘反射’可以解决避免分支判断的问题。
IFactory operFactory = new AddFactory();
Operation oper = operFactory.CreateOperation();
oper.NumberA = 1;
oper.NumberB = 2;
double result=oper.GetResult();
1.4 抽象工厂模式
工厂方法模式
抽象工厂
只有一个User类和User操作类的时候,是只需要工厂方法模式的,但现在显然你数据库中有很多的表,而SQL Server与Access又是两大不同的分类,所以解决这种涉及到多个产品系列的问题,有一个专门的工厂模式叫抽象工厂模式。
再增加一个其它的表,需要增加至少三个类,编程是门艺术,这样大批量的改动,显然是非常丑陋的做法。
最优做法,反射+配置文件+抽象工厂
2 结构型模式
不兼容结构的协调-适配器模式(适配调用某个类的一个或多个接口)
处理多维度变化-桥接模式(手机与手机软件)
树形结构的处理-组合模式(总部-分布-子公司)
扩展系统功能-装饰模式(人一层一层的穿衣服)
提供统一入口-外观模式(一个类为多个子系统(类)提供统一的行为接口)
实现对象复用-享元模式
对象的间接访问-代理模式(一个类可以在系统的任何地方替代被代理的类)
2.1 适配器模式
简单地说,就是需要的东西就在面前,但却不能使用,而短时间又无法改造它,于是我们就想办法适配它
2.2 桥接模式
桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立地变化。[DP]什么叫抽象与它的实现分离,这并不是说,让抽象类与其派生类分离,因为这没有任何意义。实现指的是抽象类和它的派生类用来实现自己的对象[DPE]
桥接模式是合成聚合原则的运用,合成/聚合复用原则(CARP),尽量使用合成/聚合,尽量不要使用类继承。[J&DP]
Implementor类
abstract class Implementor
{
public abstract void Operation();
}
ConcreteImplementorA和ConcreteImplementorB等派生类
class ConcreteImplementorA : Implementor
{
public override void Operation()
{
Console.WriteLine("具体实现A的方法执行");
}
}
class ConcreteImplementorB : Implementor
{
public override void Operation()
{
Console.WriteLine("具体实现B的方法执行");
}
}
Abstraction类
class Abstraction
{
protected Implementor implementor;
public void SetImplementor(Implementor implementor)
{
this.implementor = implementor;
}
public virtual void Operation()
{
implementor.Operation();
}
}
RefinedAbstraction类
class RefinedAbstraction : Abstraction
{
public override void Operation()
{
implementor.Operation();
}
}
继承方式实现
组合/聚合原则实现
2.3 组合模式
组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。[DP]
2.4 装饰模式
装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。[DP]
把类中的装饰功能从类中搬移去除,这样可以简化原有的类。有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。
2.5 外观模式
外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。[DP]
四个子系统的类
class SubSystemOne
{
public void MethodOne()
{
Console.WriteLine(" 子系统方法一");
}
}
class SubSystemTwo
{
public void MethodTwo()
{
Console.WriteLine(" 子系统方法二");
}
}
class SubSystemThree
{
public void MethodThree()
{
Console.WriteLine(" 子系统方法三");
}
}
class SubSystemFour
{
public void MethodFour()
{
Console.WriteLine(" 子系统方法四");
}
}
外观类
客户端调用
2.6 代理模式
代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。[DP]
//Subject类,定义了RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使
//用Proxy。
abstract class Subject
{
public abstract void Request();
}
//RealSubject类,定义Proxy所代表的真实实体。
class RealSubject : Subject
{
public override void Request()
{
Console.WriteLine("真实的请求");
}
}
//Proxy类,保存一个引用使得代理可以访问实体,并提供一个与Subject的接口相同的接口,这样代理就可以
//用来替代实体。
class Proxy : Subject
{
RealSubject realSubject;
public override void Request()
{
if (realSubject == null)
{
realSubject = new RealSubject();
}
realSubject.Request();
}
}
//客户端代码
static void Main(string[] args)
{
Proxy proxy = new Proxy();
proxy.Request();
Console.Read();
}
3 行为型模式
请求的的链式处理-职责链模式(解决多层ifelse分支,如请假多层领导审批)
请求发送者与接受者解耦-命令模式(人-遥控器-电视)
自定义语言的实现-解释器模式
遍历聚合对象中的元素-迭代器模式(一个对象代替目标对象,遍历目标对象内的数组)
协调多个对象的交互-中介者模式(多对多引用)
撤销功能的实现-备忘录模式(游戏离线时,保存游戏进度)
对象间的联动-观察者模式(解决一对多依赖关系)
对象状态及其转化-状态模式
算法的封装与切换-策略模式
定义算法的框架-模版方法模式(模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势)
操作复杂对象结构-访问者模式
3.1 职责链模式
职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。[DP]。 针对多重嵌套的if else语句
满足条件的话当前对象执行,不满足条件转移到下个对象,初始化时当前对象要指定下个对象。
Handler类,定义一个处理请示的接口。
ConcreteHandler类,具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理之,否则就将该请求转发给它的后继者。ConcreteHandler1,当请求数在0到10之间则有权处理,否则转到下一位。
ConcreteHandler2,当请求数在10到20之间则有权处理,否则转到下一位。
ConcreteHandler3,当请求数在20到30之间则有权处理,否则转到下一位。
客户端代码,向链上的具体处理者对象提交请求。
3.2 命令模式
命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。[DP]
Command类,用来声明执行操作的接口。
abstract class Command
{
protected Receiver receiver;
public Command(Receiver receiver)
{
this.receiver = receiver;
}
abstract public void Execute();
}
ConcreteCommand类,将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute。
class ConcreteCommand : Command
{
public ConcreteCommand(Receiver receiver) : base(receiver)
{ }
public override void Execute()
{
receiver.Action();
}
}
Invoker类,要求该命令执行这个请求。
class Invoker
{
private Command command;
public void SetCommand(Command command)
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
}
Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者。
class Receiver
{
public void Action()
{
Console.WriteLine("执行请求!");
}
}
客户端代码,创建一个具体命令对象并设定它的接收者。
static void Main(string[] args)
{
Receiver r = new Receiver();
Command c = new ConcreteCommand(r);
Invoker i = new Invoker();
i.SetCommand(c);
i.ExecuteCommand();
Console.Read();
}
3.3 迭代器模式
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。[DP]。
Iterator迭代器抽象类
Aggregate聚集抽象类
ConcreteIterator具体迭代器类,继承Iterator
ConcreteAggregate具体聚集类 继承Aggregate
客户端代码
3.4 中介者模式
中介者模式(Mediator),用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。[DP]
解决n个对象,需要在自己类内引用除自己以外的n-1个类的情况
联合国类似于中介者
Mediator类 抽象中介者类
Colleague类 抽象同事类
ConcreteMediator类 具体中介者类
ConcreteColleague1和ConcreteColleague2等各种同事对象
客户端调用
3.5 备忘录模式
备忘录(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。[DP]
Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。Memento(备忘录):负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。备忘录有两个接口,Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。Originator能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。
发起人(Originator)类
备忘录(Memento)类
管理者(Caretaker)类
客户端程序
3.6 观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。[DP]
Subject类,可翻译为主题或抽象通知者,一般用一个抽象类或者一个接口实现。
abstract class Subject
{
private IList<Observer> observers = new List<Observer>();
//增加观察者
public void Attach(Observer observer)
{
observers.Add(observer);
}
//移除观察者
public void Detach(Observer observer)
{
observers.Remove(observer);
}
//通知
public void Notify()
{
foreach (Observer o in observers)
{
o.Update();
}
}
}
Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
abstract class Observer
{
public abstract void Update();
}
ConcreteSubject类,叫做具体主题或具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
class ConcreteSubject : Subject
{
private string subjectState;
//具体被观察者状态
public string SubjectState
{
get { return subjectState; }
set { subjectState = value; }
}
}
ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。
class ConcreteObserver : Observer
{
private string name;
private string observerState;
private ConcreteSubject subject;
public ConcreteObserver(ConcreteSubject subject, string name)
{
this.subject = subject;
this.name = name;
}
public override void Update()
{
observerState = subject.SubjectState;
Console.WriteLine("观察者{0}的新状态是{1}", name, observerState);
}
public ConcreteSubject Subject
{
get { return subject; }
set { subject = value; }
}
}
客户端代码
static void Main(string[] args)
{
ConcreteSubject s = new ConcreteSubject();
s.Attach(new ConcreteObserver(s, "X"));
s.Attach(new ConcreteObserver(s, "Y"));
s.Attach(new ConcreteObserver(s, "Z"));
s.SubjectState = "ABC";
s.Notify();
Console.Read();
}
调用的观察者的update接口不存在,或者观察者的接口名称不同时,通知的功能就无法完成。
通过事件委托的方式弥补不足之处。
“老板”类和“前台秘书”类
客户端代码
3.7 状态模式
状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。[DP]
State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。
abstract class State
{
public abstract void Handle(Context context);
}
ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
客户端代码
状态机更加灵活,有n个状态,可以让n个状态随机组合成不同的状态机。而上述状态模式,只适合于红绿灯等固定的情况,从红绿灯中抽取只有红灯黄灯循环闪烁,则需要修改state的内部逻辑,重新指定下一个状态。
3.8 策略模式
策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。[DP]
Strategy类,定义所有支持的算法的公共接口
//抽象算法类
abstract class Strategy
{
//算法方法
public abstract void AlgorithmInterface();
}
ConcreteStrategy,封装了具体的算法或行为,继承于Strategy
//具体算法A
class ConcreteStrategyA : Strategy
{
//算法A实现方法
public override void AlgorithmInterface()
{
Console.WriteLine("算法A实现");
}
}
//具体算法B
class ConcreteStrategyB : Strategy
{
//算法B实现方法
public override void AlgorithmInterface()
{
Console.WriteLine("算法B实现");
}
}
//具体算法C
class ConcreteStrategyC : Strategy
{
//算法C实现方法
public override void AlgorithmInterface()
{
Console.WriteLine("算法C实现");
}
}
Context,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
客户端代码
简单工厂+策略模式,将客户端的判断逻辑转移到context内部
改造后的CashContext
客户端代码 根据传入的内容决定初始化那种算法
3.9 模版方法
模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。[DP]
AbstractClass是抽象类,其实也就是一抽象模板,定义并实现了一个模版方法。这个模版方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
ConcreteClass,实现父类所定义的一个或多个抽象方法。每一个AbstractClass都可以有任意多个ConcreteClass与之对应,而每一个ConcreteClass都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
客户端调用
static void Main(string[] args)
{
AbstractClass c;
c = new ConcreteClassA();
c.TemplateMethod();
c = new ConcreteClassB();
c.TemplateMethod();
Console.Read();
}