设计模式学习笔记(一)——面向对象设计模式与原则

 

1.设计模式的概念
设计模式描述了软件设计过程中某一类常见问题的一般性的解决方案。

2.面向对象设计模式
面向对象设计模式描述了类与相互通信的对象之间的组织关系。目的是应对变化、提高复用、减少改变。

3.什么是对象:
1)从概念层面讲,对象是某种拥有职责的抽象;
2)从规格层面讲,对象是一系列可以被其他对象使用的公共接口;
3)从语言实现层面来看,对象封装了代码和数据(也就是行为和状态)。
如果我们抛开代码的实现来看对象的概念,那么它应该就像个具体的物体,
比如说:榔头,从概念层面讲,榔头有它的职责,也就是它是做什么用的(用来砸钉子,当然还会有其他用途,如防身),从规格层面讲,比如人使用榔头砸钉子。

4.面向对象的设计模式有三大原则
1)接口编程,实现多态可以减少代码的修改。
比如说在《Head First Design Patterns》中有一个例子,说一个有关鸭子的游戏。游戏当中有很多种的鸭子,如:野鸭,木头鸭,鸭子模型。我们首先会想到做一个抽象类:abstract class Duck,Duck当中有很多的抽象属性和方法,如quack。我们用子类继承的时候都会实例化这个方法。

public abstract class Duck {
	public abstract void quack();
}

继承抽象类,并覆盖抽象方法,抽象方法只会存在于抽象类中;

public class MallardDuck extends Duck{
	@Override
	public void quack() {
		System.out.println("I can quack");
	}
}


当程序成型后,我们有了很多种鸭子,突然,我们发现有的鸭子会飞,我们会在Duck中在加上一个抽象方法abstract void fly();
于是我们不得不在所有的子类当中添加fly的实现,有人会说,如果我们在Duck中直接添加fly的实现,不就不用在子类中添加实现了吗?
这时我们换一种想法,如果我们把这些方法都提取出来,把它变成Duck的成员,好像问题就会简单些。

2)优先使用对象组合,而不是类的继承。
这就使说多使用“like a”,少使用“is a”。回刚才的例子,换个角度考虑Duck及其功能,我们设计一个fly的接口和一些具体的飞行方法。

public interface FlyBehavior {
  void fly();
}
public class FlyWithWing implements FlyBehavior {
	@Override
	public void fly() {
		System.out.println("I can fly.");
	}
}
public class FlyNoWay implements FlyBehavior {
	@Override
	public void fly() {
		System.out.println("I can't fly");
	}
}

好了,对于Duck来说,现在它应该有一个(like a)fly的方法

public abstract class Duck {
    public Duck() {
        
    }
    public FlyBehavior flybehavior;
}

现在我们再来实现两种鸭子

public class ModelDuck extends Duck {
    public ModelDuck() {
        flybehavior = new FlyNoWay();
    }
}
public class MallardDuck extends Duck {
    public MallardDuck() {
        flybehavior = new FlyWithWing();
    }
}

这样如果要是在加上某种行为的话,我们就不必在每一种鸭子上下功夫。把注意力放在我们关心的鸭子品种上。
3)封装变化点,实现松耦合,这点不用多说了。
课程中提到,编码当中的设计模式使用不是我们在编程之初就定下来的,应该是重构得到设计模式(Refactoring to Patterns)。哦,原来是这样,也好理解。在编码中遇到问题,然后想想应对方式。哈哈,我原来认为开始编程时就指定我们用什么设计模式呢。
下面说说设计原则:
a.单一职责原则(SRP):一个类应仅有一个引起它变化的原因。
b.开放封闭原则(OCP):类模块应可扩展,不可修改。这里要说明一下,扩展和修改是不同的。比如:我们要在加一种ModelDuck,那么我们写一个ModelDuck的类继承Duck,这叫扩展,不是修改。什么是修改,就好像我们开始说的那种作法,为了加一个fly的功能,我们要把所有的子类中加入不同的实现,这叫修改。
c.Liskov替换原则:子类可替换基类。
d.依赖倒置原则:高层模块不依赖于低层模块,二者都依赖于抽象。还是刚才的例子:Duck是一个高层模块,fly是低层模块。Duck不依赖于fly,高层模块的改变慢,而低层模块的改变慢。
抽象不应依赖于实现细节,实现细节应依赖于抽象。fly是一个抽象,它不依赖如何飞行。
e.接口隔离原则:不强迫客户程序依赖于它们不用的方法(有道理,木头鸭子不会飞为什么要让它实现飞的功能。)
最后有人提问接口和抽象类的区别:
接口可以多继承,抽象类只能单继承。接口定义组件间的合同。使用抽象类为一个is a的关系。

 

---摘自http://www.cnblogs.com/kid-li/archive/2006/03/29/361899.html

 

posted @ 2015-10-27 09:48  幺刀  阅读(231)  评论(0编辑  收藏  举报