设计原则:
1.单一职责原则:尽量保证每一个类或者接口拥有单一的职责,即专业性,比如说一个人学的东西太广就容易不精,代码也是一样,一项功能块的修改有可能会影响其他的功能块。
2.里氏替换原则:子类尽量不要重写和重载其父类的方法,可能会导致子类无法使用父类的功能,即子类继承只为了扩展不为了修改。
3.依赖倒置原则:细节依赖抽象,业务逻辑牵一发而动全身,通过接口进行类之间的依赖可进一步解耦。
4.接口隔离原则:类似于单一原则,使接口具有单一功能,或者说一个类要继承最小的接口,即接口内的方法都能用到,不存在冗余。
5.迪米特原则:尽量降低类与类之间的耦合性,一个类对另一个类的信息知道的越少越好,比如说,我想要一辆车,我不需要知道车是怎么组成的,我只是拿来用。
6.开闭原则:对于已经具有可用功能的项目来说,不要去修改任何代码,因为这可能会带来很多新的问题,所以只扩展、不修改。
设计模式:
1.单例模式:只存在一个实例,通常自行实例化,减少内存开销,为了适应某些时刻资源只能被一个对象使用的情况。注意不要对他失去控制从而造成内存泄漏,因为大家操作的是同一个对象,也就是操作同一块资源,所以也要注意线程安全问题(加上synchronized关键字)。
2.工厂模式:
*静态工厂模式:静态方法getInstance()返回实例,也可以传入参数获取不同类型的实例,判断都是在getInstance方法里面。
*工厂方法模式:好比接口回调,不同的类实现同一个接口,然后不同的类的对象转型成接口对象,从而调用同一个方法(但是却是不同的实现)。
*抽象工厂模式:即建一个总工厂先抽象一层,然后再建两个具体的工厂实现总工厂,然后相应的类分别继承适合自己的具体工厂,从而调用不同的方法实现。
3.模板方法模式:相当于一张说明书,父类定义了一些需要子类去实现细节的方法,然后定义一个方法,里面按照父类设计者的思路调用了这些方法,子类中只需要实现细节并且调用模板方法即可。
/// <summary>
/// 抽象类
/// </summary>
public abstract class AbstractClass
{
// 一些抽象行为,放到子类去实现
public abstract void PrimitiveOperation1();
public abstract void PrimitiveOperation2();
/// <summary>
/// 模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,它们推迟到子类去实现。
/// </summary>
public void TemplateMethod()
{
PrimitiveOperation1();
PrimitiveOperation2();
Console.WriteLine("Done the method.");
}
}
4.建造者模式:比如说你要建造一所房子,他有自己的流程,打地基、和水泥、砌砖等等,建造者模式就是把这些实现的细节封装在内部,然后外部调用build公有方法开始构建,其内部就会按照一定的流程去实现。
一个典型的复杂类对象代码示例如下:
class Productor {
private Part partA;
private Part partB;
private Part partC;
// 这些是各个部件的set和get的方法,在此省略。。。
}
这是抽象的Builder:
abstract class Builder {
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
}
继承Builder的具体的建造者:
class ConcreteBuilder extends Builder {
private Product product;
// 创建partA
public void buildPartA() {
// 在此创建出部件
Part partA = new PartA();
// ......
// 把partA传递给product
product.setPartA(partA);
}
// 创建partB
public void buildPartB() {
// 在此创建出部件
Part partB = new PartB();
// ......
// 把partB传递给product
product.setPartA(partB);
}
// 创建partC
public void buildPartC() {
// 在此创建出部件
Part partC = new PartC();
// ......
// 把partC传递给product
product.setPartA(partC);
}
// 返回复杂产品对象
public void getProduct() {
return this.product;
}
}
这是导演,负责流程规范,在导演类中可以注入建造者对象。
class Director {
private Builder concretebuilder;
// 构造方法中也可以传递builder
public Director(Builder builder) {
this.concretebuilder = builder;
}
// 传递builder
public void setBuilder(Builder builder) {
this.concretebuilder = builder;
}
// 这个方法用来规范流程,产品构建和组装方法
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
// 客户端使用:
class Main {
public static void main(String[] args) {
// 对于客户端而言,只需要关心具体的建造者,无需关心产品内部构建流程。我如果需要其他的复杂产品对象,只需要选择其他的建造者,如果需要扩展,则只需要写一个新的builder就行。如果可以,这个建造者甚至可以用配置文件做,增加更多的扩展性。
Builder builder = new ConcreteBuilder();
// 把建造者注入导演
Director director = new Director(builder);
// 指挥者负责流程把控
director.construct();
// 建造者返回一个组合好的复杂产品对象
Productor productor = builder.getProductor();
}
}
5.代理模式:表面上是代理做出的动作,实际上真正的动作执行者是被代理者,比如卖毛巾,生产商和销售点之间就是代理关系。
代理模式到底好处在哪里呢??
那先要说一下代理模式中的三种角色了。
抽象角色:声明真实对象和代理对象的共同接口。
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
代理模式的一个好处就是对外部提供统一的接口方法,而代理类在接口中实现对真实类的附加操作行为,从而可以在不影响外部调用情况下,进行系统扩展。也就是说,我要修改真实角色的操作的时候,尽量不要修改他,而是在外部在“包”一层进行附加行为,即代理类。例如:接口A有一个接口方法operator(),真实角色:RealA实现接口A,则必须实现接口方法operator()。客户端Client调用接口A的接方法operator()。现在新需求来了,需要修改RealA中的operator()的操作行为。怎么办呢?如果修改RealA就会影响原有系统的稳定性,还要重新测试。这是就需要代理类实现附加行为操作。创建代理ProxyA实现接口A,并将真实对象RealA注入进来。ProxyA实现接口方法operator(),另外还可以增加附加行为,然后调用真实对象的operator()。从而达到了“对修改关闭,对扩展开放”,保证了系统的稳定性。我们看客户端Client调用仍是接口A的接口方法operator(),只不过实例变为了ProxyA类了而已。也就是说代理模式实现了ocp原则。
//定义了接口 2 interface SaleTowelIntertace 3 { 4 void sellTowel(); 5 } 6 //毛巾的生产类 7 class TowelProduce : SaleTowelIntertace 8 { 9 string ConsumerName; 10 TowelProduce(string consumer_name) 11 { 12 ConsumerName = consumer_name; 13 } 14 void sellTowel() 15 { 16 Console.WriteLine("毛巾卖给了{0}",ConsumerName); 17 } 18 } 19 //卖毛巾的代理类 20 class TowelSaleProxy : SaleTowelIntertace 21 { 22 TowelProduce tp; 23 TowelSaleProxy(string consumner_name) 24 { 25 tp = new TowelProduce(consumer_name); 26 } 27 void sellTowel() 28 { 29 tp.sellTowel(); 30 } 31 }6.原型模式:原型模式就是建一个类,然后实现Cloneable接口,重写clone方法。
他的优势在于,使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
class Prototype implements Cloneable {
public Prototype clone(){
Prototype prototype = null;
try{
prototype = (Prototype)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return prototype;
}
}
class ConcretePrototype extends Prototype{
public void show(){
System.out.println("原型模式实现类");
}
}
public class Client {
public static void main(String[] args){
ConcretePrototype cp = new ConcretePrototype();
for(int i=0; i< 10; i++){
ConcretePrototype clonecp = (ConcretePrototype)cp.clone();
clonecp.show();
}
}
}
7.中介者模式:
在面向对象编程中,一个类必然会与其他的类发生依赖关系,完全独立的类是没有意义的。一个类同时依赖多个类的情况也相当普遍,既然存在这样的情况,说明,一对多的依赖关系有它的合理性,适当的使用中介者模式可以使原本凌乱的对象关系清晰,但是如果滥用,则可能会带来反的效果。一般来说,只有对于那种同事类之间是网状结构的关系,才会考虑使用中介者模式。可以将网状结构变为星状结构,使同事类之间的关系变的清晰一些。
中介者模式是一种比较常用的模式,也是一种比较容易被滥用的模式。对于大多数的情况,同事类之间的关系不会复杂到混乱不堪的网状结构,因此,大多数情况下,将对象间的依赖关系封装的同事类内部就可以的,没有必要非引入中介者模式。滥用中介者模式,只会让事情变的更复杂。
ConcreteMediator:具体的中介者实现对象。它需要了解并为维护每个同事对象,并负责具体的协调各个同事对象的交互关系。
Colleague:同事类的定义,通常实现成为抽象类,主要负责约束同事对象的类型,并实现一些具体同事类之间的公共功能,比如,每个具体同事类都应该知道中介者对象,也就是每个同事对象都会持有中介者对象的引用,这个功能可定义在这个类中。
ConcreteColleague:具体的同事类,实现自己的业务,需要与其他同事对象交互时,就通知中介对象,中介对象会负责后续的交互。
/// <summary>
/// 同事类的抽象父类
/// </summary>
public abstract class Colleague
{
/// <summary>
/// 持有中介者对象,每一个同事类都知道它的中介者对象
/// </summary>
private Mediator mediator;
/// <summary>
/// 构造方法,传入中介者对象
/// </summary>
/// <param name="mediator">中介者对象</param>
protected Colleague(Mediator mediator)
{
this.mediator = mediator;
}
/// <summary>
/// 获取当前同事类对应的中介者对象
/// </summary>
/// <returns>对应的中介者对象</returns>
public Mediator GetMediator()
{
return mediator;
}
}
/// <summary>
/// 具体的同事类A
/// </summary>
public class ConcreteColleagueA : Colleague
{
/// <summary>
/// 调用父类的构造函数
/// </summary>
/// <param name="mediator"></param>
public ConcreteColleagueA(Mediator mediator):base(mediator)
{
}
/// <summary>
/// 执行某些业务功能
/// </summary>
public void SomeOperation()
{
//在需要跟其他同事通信的时候,通知中介者对象
base.GetMediator().Change(this);
}
}
/// <summary>
/// 具体的同事类B
/// </summary>
public class ConcreteColleagueB : Colleague
{
/// <summary>
/// 调用父类的构造函数
/// </summary>
/// <param name="mediator"></param>
public ConcreteColleagueB(Mediator mediator)
: base(mediator)
{
}
/// <summary>
/// 执行某些业务功能
/// </summary>
public void SomeOperation()
{
//在需要跟其他同事通信的时候,通知中介者对象
base.GetMediator().Change(this);
}
}
/// <summary>
/// 中介者,定义各个同事对象通信的接口
/// </summary>
public interface Mediator
{
void Change(Colleague colleague);
}
/// <summary>
/// 具体的中介者实现
/// </summary>
public class ConcreteMediator
{
/// <summary>
/// 持有并维护同事A
/// </summary>
private ConcreteColleagueA colleagueA;
/// <summary>
/// 持有并维护同事B
/// </summary>
private ConcreteColleagueB colleagueB;
/// <summary>
/// 设置中介者需要了解并维护的同事A对象
/// </summary>
/// <param name="colleague">同事A对象</param>
public void SetConcreteColleagueA(ConcreteColleagueA colleague)
{
colleagueA = colleague;
}
/// <summary>
/// 设置中介者需要了解并维护的同事B对象
/// </summary>
/// <param name="colleague">同事B对象</param>
public void SetConcreteColleagueB(ConcreteColleagueB colleague)
{
colleagueB = colleague;
}
public void Changed(Colleague colleague)
{
//某个同事类发生了变化,通常需要与其他同事交互
//具体协调相应的同事对象来实现协作行为
}
}
8.桥梁模式:将抽象和实现解耦,使得两者可以独立地变化。例如,JDBC。
9.状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样。
/// <summary>
/// Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
/// </summary>
public class Context
{
private State state;
/// <summary>
/// 定义Context的初始状态
/// </summary>
/// <param name="state"></param>
public Context(State state)
{
this.state = state;
}
/// <summary>
/// 可读写的状态属性,用于读取和设置新状态
/// </summary>
public State State
{
get { return state; }
set { state = value; }
}
/// <summary>
/// 对请求做处理,并设置下一个状态
/// </summary>
public void Request()
{
state.Handle(this);
}
}
/// <summary>
/// 抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
/// </summary>
public abstract class State
{
public abstract void Handle(Context context);
}
/// <summary>
/// 具体状态类,每一个子类实现一个与Context的一个状态相关的行为
/// </summary>
public class ConcreteStateA : State
{
/// <summary>
/// 设置ConcreteStateA的下一个状态是ConcreteStateB
/// </summary>
/// <param name="context"></param>
public override void Handle(Context context)
{
Console.WriteLine("当前状态是 A.");
context.State = new ConcreteStateB();
}
}
public class ConcreteStateB : State
{
/// <summary>
/// 设置ConcreteStateB的下一个状态是ConcreteSateA
/// </summary>
/// <param name="context"></param>
public override void Handle(Context context)
{
Console.WriteLine("当前状态是 B.");
context.State = new ConcreteStateA();
}
}
10.访问者模式:
符合单一职责原则:凡是适用访问者模式的场景中,元素类中需要封装在访问者中的操作必定是与元素类本身关系不大且是易变的操作,使用访问者模式一方面符合单一职责原则,另一方面,因为被封装的操作通常来说都是易变的,所以当发生变化时,就可以在不改变元素类本身的前提下,实现对变化部分的扩展。
扩展性良好:元素类可以通过接受不同的访问者来实现对不同操作的扩展。
abstract class Element {
public abstract void accept(IVisitor visitor);
public abstract void doSomething();
}
interface IVisitor {
public void visit(ConcreteElement1 el1);
public void visit(ConcreteElement2 el2);
}
class ConcreteElement1 extends Element {
public void doSomething(){
System.out.println("这是元素1");
}
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
class ConcreteElement2 extends Element {
public void doSomething(){
System.out.println("这是元素2");
}
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
class Visitor implements IVisitor {
public void visit(ConcreteElement1 el1) {
el1.doSomething();
}
public void visit(ConcreteElement2 el2) {
el2.doSomething();
}
}
class ObjectStruture {
public static List<Element> getList(){
List<Element> list = new ArrayList<Element>();
Random ran = new Random();
for(int i=0; i<10; i++){
int a = ran.nextInt(100);
if(a>50){
list.add(new ConcreteElement1());
}else{
list.add(new ConcreteElement2());
}
}
return list;
}
}
public class Client {
public static void main(String[] args){
List<Element> list = ObjectStruture.getList();
for(Element e: list){
e.accept(new Visitor());
}
}
}
11.观察者模式:在JAVA语言的java.util库里面,提供了一个Observable类以及一个Observer接口,构成JAVA语言对观察者模式的支持。
/// <summary>
/// 抽象主题类
/// </summary>
public abstract class Subject
{
private IList<Observer> observers = new List<Observer>();
/// <summary>
/// 增加观察者
/// </summary>
/// <param name="observer"></param>
public void Attach(Observer observer)
{
observers.Add(observer);
}
/// <summary>
/// 移除观察者
/// </summary>
/// <param name="observer"></param>
public void Detach(Observer observer)
{
observers.Remove(observer);
}
/// <summary>
/// 向观察者(们)发出通知
/// </summary>
public void Notify()
{
foreach (Observer o in observers)
{
o.Update();
}
}
}
/// <summary>
/// 抽象观察者类,为所有具体观察者定义一个接口,在得到通知时更新自己
/// </summary>
public abstract class Observer
{
public abstract void Update();
}
/// <summary>
/// 具体观察者或具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
/// </summary>
public class ConcreteSubject : Subject
{
private string subjectState;
/// <summary>
/// 具体观察者的状态
/// </summary>
public string SubjectState
{
get { return subjectState; }
set { subjectState = value; }
}
}
/// <summary>
/// 具体观察者,实现抽象观察者角色所要求的更新接口,已是本身状态与主题状态相协调
/// </summary>
public class ConcreteObserver : Observer
{
private string observerState;
private string name;
private ConcreteSubject subject;
/// <summary>
/// 具体观察者用一个具体主题来实现
/// </summary>
public ConcreteSubject Subject
{
get { return subject; }
set { subject = value; }
}
public ConcreteObserver(ConcreteSubject subject, string name)
{
this.subject = subject;
this.name = name;
}
/// <summary>
/// 实现抽象观察者中的更新操作
/// </summary>
public override void Update()
{
observerState = subject.SubjectState;
Console.WriteLine("The observer's state of {0} is {1}", name, observerState);
}
}
4.3 客户端代码
class Program
{
static void Main(string[] args)
{
// 具体主题角色通常用具体自来来实现
ConcreteSubject subject = new ConcreteSubject();
subject.Attach(new ConcreteObserver(subject, "Observer A"));
subject.Attach(new ConcreteObserver(subject, "Observer B"));
subject.Attach(new ConcreteObserver(subject, "Observer C"));
subject.SubjectState = "Ready";
subject.Notify();
Console.Read();
}
}
12.门面模式(外观模式):相当于一个中间人,比如说你到银行办理业务,你不能直接和柜台人员交流,先得有一个前台人员和你沟通,然后他们和柜台人员沟通。
太多了,总结不过来了,结合android例子会比较好记:点击打开链接