写在前面:
本文参考:http://c.biancheng.net/design_pattern/
本文用于交流学习。
简介
类间关系
依赖
耦合度最弱。
使用类调用依赖类的对象。
如:使用类A(人)------>被依赖的类B(手机)
关联
- 一般关联关系
关联可以是双向的,也可以是单向的。
使用类将被关联类的对象做为成员变量。
——或使用类——>被关联的类
如老师和学生。 - 聚合关系
强关联关系。整体和部分的关系。has-a。
整体类将部分类的对象做为成员变量。成员变量可以独立存在。
如学校和老师。
整体◊——部分 - 组合关系
更强烈的聚合关系。contains-a。
整体对象可以控制部分对象的生命周期,一旦整体对象不存在,部分对象也将不存在,部分对象不能脱离整体对象而存在。
如人和眼睛。
整体◆——部分
泛化(继承)
is-a。
父类◁——子类。
实现(接口)
接口◁------实现类
面向对象设计原则
开闭原则(open closed principle,OCP)
对扩展开放,对修改关闭。
对象:软件实体----项目中的模块、类与接口、方法。
里氏替换原则(Liskov substitution principle,LSP)
继承必须确保超类(父类)所有性质在子类中仍然成立。
作用:继承的一个标准。实现开闭原则的一种方式。
依赖倒置原则(dependence inversion principle,DIP)
高层模块不应依赖于低层模块,两者都应该依赖抽象;抽象不应该依赖于细节,细节应该依赖于抽象。
核心思想:面向接口编程,不要面向实现编程。
作用:降低类间耦合。实现开闭原则的一种重要方式。
单一职责原则(single responsibility principle,SRP)
一个类应该有且仅有一个引起它变化的原因,否则类应被拆分。
接口隔离原则(interface segregation principle,ISP)
一个类对另一个类的依赖应该建立在最小的接口上,客户端不应该被迫依赖它不使用的方法。
迪米特法则/最少知识原则(law of Demeter,LoD/least knowledge principle,LKP)
只与你的直接朋友交谈,不跟陌生人说话。
直接朋友:当前对象本身,当前对象的成员对象,当前对象所创建的对象,当前对象的方法参数等。
合成复用原则(composite reuse principle,CRP)
软件复用时,尽量先使用组合或聚合等关联关系实现,其次才考虑继承关系来实现。
设计模式
1.单例模式(Singleton)
一个类只有一个实例,由类自行创建。
懒汉式:只在第一次使用时创建实例对象,需要使用volatile,synchronized保证线程安全(每次访问要同步),会消耗更多资源。
public class Singleton {
private static volatile Singleton instance = null;
private LazySingleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
饿汉式:提前创建好实例对象,线程安全。
public class Singleton {
private static final Singleton instance = new HungrySingleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
2.原型模式(Prototype)
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。原型实例指定了要创建的对象的种类。
抽象原型类:规定了具体原型对象必须实现的接口。
具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
访问类:使用具体原型类中的 clone() 方法来复制新的对象。
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
//Java 的 Object 类 clone() 方法
//具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆
class Prototype implements Cloneable {
String proporty="";
Prototype() {
System.out.println("Prototype");
}
public Object clone() throws CloneNotSupportedException {
System.out.println("Prototype copy");
return (Prototype) super.clone();
}
}
public class PrototypeTest {
public static void main(String[] args) throws CloneNotSupportedException {
Prototype obj1 = new Prototype ();
Prototype obj2 = (Prototype) obj1.clone();
System.out.println(bj1 == obj2); //false
System.out.println(obj1.proporty == obj2.proporty); //true
}
}
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
3.工厂模式
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作交给具体工厂类。
如客户想要吃早餐。
- 对于简单工厂,早餐店售卖的早餐类型有限,客户在早餐店挑选一种早餐,早餐店创建一个早餐给客户。当客户想要新的早餐,早餐点就需要在售卖类型里添加新的类型。
- 对于工厂方法模式,售卖的早餐类型有限,客户在早餐店挑选一种早餐,由早餐店下面对应的部门生产。当客户想要吃新的早餐,就增加一个新的部门。这个部门只生产这种早餐(如牛奶由牛奶部门生产)。
- 对于抽象工厂模式,售卖的早餐类型有限,客户在早餐店挑选一种早餐,由早餐店下面该早餐类型所属的部门生产。当客户想要吃新的早餐类型,就增加一个新的部门。这个部门生产一类早餐(如牛奶由饮品部门生产,饮品部门还生产果汁等)。
简单工厂模式(Simple Factory Pattern)
创建实例的方法通常为静态方法,因此简单工厂模式又叫作静态工厂方法模式(Static Factory Method Pattern)。
角色:简单工厂,抽象产品,具体产品。
public interface Breakfast {
void sale();
}
public class Breakfast1 implements Breakfast {
public static final int id=1;
@Override
public void sale() {
// TODO Auto-generated method stub
System.out.println("Breakfast1");
}
}
public class Breakfast2 implements Breakfast {
public static final int id=2;
@Override
public void sale() {
// TODO Auto-generated method stub
System.out.println("Breakfast2");
}
}
public class SimpleFactory { //早餐店
public static Breakfast makeBreakfast(int id) {
switch(id) {
case 1: return new Breakfast1();
case 2: return new Breakfast2();
}
return null;
}
}
public class Client { //客户
public static void main(String[] args) {
// TODO Auto-generated method stub
Breakfast bf1=SimpleFactory.makeBreakfast(Breakfast1.id);
Breakfast bf2=SimpleFactory.makeBreakfast(Breakfast2.id);
bf1.sale();
bf2.sale();
}
}
工厂方法模式
角色:抽象工厂,具体工厂,抽象产品(1个),具体产品。
// Breakfast接口及其实现类同上
public interface AbstractFactory {
Breakfast makeBreakfast();
}
public class Breakfast1Factory implements AbstractFactory {
@Override
public Breakfast makeBreakfast() {
// TODO Auto-generated method stub
return new Breakfast1();
}
}
public class Breakfast2Factory implements AbstractFactory {
@Override
public Breakfast makeBreakfast() {
// TODO Auto-generated method stub
return new Breakfast2();
}
}
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Breakfast bf1=new Breakfast1Factory().makeBreakfast();
Breakfast bf2=new Breakfast2Factory().makeBreakfast();
bf1.sale();
bf2.sale();
}
}
抽象工厂模式
角色:抽象工厂,具体工厂,抽象产品(多个),具体产品。
public interface Drink{
void sale();
}
public interface Bread {
void sale();
}
public class Milk implements Drink {
@Override
public void sale() {
// TODO Auto-generated method stub
System.out.println("Milk ");
}
}
public class SweetBread implements Bread {
@Override
public void sale() {
// TODO Auto-generated method stub
System.out.println("SweetBread ");
}
}
public interface AbstractFactory {
Drink makeBreakfast();
Bread makeBreakfast();
}
public class BreakfastFactory implements AbstractFactory {
@Override
public Drink makeDrink() {
// TODO Auto-generated method stub
return new Milk();
}
@Override
public Bread makeBread() {
// TODO Auto-generated method stub
return new SweetBread();
}
}
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Drink milk=new BreakfastFactory().makeDrink();
Bread sweetBread=new BreakfastFactory().makeBread();
milk.sale();
sweetBread.sale();
}
}
4.代理模式
访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
角色:代理,抽象对象,具体对象。
public interface Buy {
void buy();
}
public class BuyTicket implements Buy {
@Override
public void buy() {
// TODO Auto-generated method stub
System.out.println("buy ticket");
}
}
public class Proxy implements Buy {
private BuyTicket buyTicket = new BuyTicket();
@Override
public void buy() {
// TODO Auto-generated method stub
System.out.println("proxy buy ticket");
buyTicket.buy();
System.out.println("proxy finish buying ticket");
}
}
public class Client {
public static void main(String[] args) {
Proxy proxy=new Proxy();
proxy.buy();
}
}
5.适配器模式
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。类似于现实生活中的数据线转化接口。
可以通过接口的多继承来实现。
6.装饰者模式
在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象。
角色:抽象构件,具体构件,抽象装饰,具体装饰。
public interface Component {
public void operation();
}
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("ConcreteComponent ");
}
}
public class Decorator implements Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void operation() {
super.operation();
addOperation();
}
public void addOperation() {
System.out.println("add operation");
}
}
7.观察者模式
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。如微信公众号的推文。
角色:抽象对象,具体对象,抽象观察者,具体观察者。
public interface Observer {
void recieve(String article);
}
public class User1 implements Observer {
@Override
public void recieve(String article) {
// TODO Auto-generated method stub
System.out.println("user1 get "+article);
}
}
public class User2 implements Observer {
@Override
public void recieve(String article) {
// TODO Auto-generated method stub
System.out.println("user2 get "+article);
}
}
//公众号
import java.util.ArrayList;
import java.util.List;
public abstract class OfficialAccount {
public List<Observer> observers = new ArrayList<Observer>();
public void add(Observer observer) {
observers.add(observer);
}
public void remove(Observer observer) {
observers.remove(observer);
}
public abstract void sendArticle();
}
//腾讯的公众号
public class Tencent extends OfficialAccount {
@Override
public void sendArticle() {
// TODO Auto-generated method stub
String article="this is tencent";
for(Observer user:observers) {
user.recieve(article);
}
}
}
public class Wechat {
public static void main(String[] args) {
// TODO Auto-generated method stub
Tencent tencent=new Tencent();
User1 u1=new User1();
User2 u2=new User2();
tencent.add(u1);
tencent.add(u2);
tencent.sendArticle();
}
}