设计模式简介
设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
设计模式四大要素
模式名称
以一个恰当的词来描述模式的问题、解决方案和效果。
问题
描述应该在何时使用设计模式。
解决方案
提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象)来解决这个问题。
效果
描述设计模式应用的效果及使用设计模式应该权衡的问题。
设计模式六大原则
开闭原则
面向对象设计/编程 终极目标(实现开闭原则)
一个是对于拓展是开放的,另一个是对于修改是关闭的
尽量不要修改已有代码
单一职责
不要让一个类承担过多的职责
里氏替换
继承父类后,尽量不要重写父类的方法。
依赖倒转
通过抽象或者接口来实现类与类之间的依赖关系。
接口隔离
建立单一接口,不要建立庞大/臃肿的接口
迪米特法则
一个实体尽可能少的与另一个实体发生接触(依赖),
只需要知道入口和结果,不必在意过程的实现。避免代码过于耦合
设计模式分类:
创建型:主要处理对象的创建,实例化对象
结构型:处理类或对象的组合
行为型:描述类或对象怎样进行交互、职责分配
创建型模式之【单例模式】
问题
对于某些场景,确保一个类只有一个实例对象是很重要的,并且这个实例是易于被访问的。
解决方案
将实例化操作隐藏在一个类中,由这个类来保证实例的创建和唯一性。
/**
* @redame 单例模式 饿汉
*/
public class SingletonObjectA {
private static SingletonObjectA instance = new SingletonObjectA();
private SingletonObjectA(){}
public static SingletonObjectA getInstance(){
return instance;
}
}
/**
* @redame 单例模式 懒汉
*/
public class SingletonObjectB {
private static volatile SingletonObjectB instance = null;
private SingletonObjectB(){}
public static SingletonObjectB getInstance(){
if(instance==null){
synchronized(instance){
if(instance == null){
instance = new SingletonObjectB();
}
}
}
return instance;
}
}
创建型模式之【工厂模式】
问题
当一个类无法确定要创建哪种类的对象,或者需要通过子类来确定具体对象的创建时。
解决方案
创建一个创建对象的工厂,工厂在程序执行过程中具体决定创建哪个对象。
/**
* @redame 普通工厂模式
*/
public class MessageFactoryA {
public static String MAIL="MAIL";
public static String SMS="SMS";
public static String WE_CHAT="WE_CHAT";
public Sender product(String type){
if(MessageFactoryA.MAIL.equals(type)){
return new MailSender();
} else if(MessageFactoryA.SMS.equals(type)){
return new SmsSender();
} else if(MessageFactoryA.WE_CHAT.equals(type)){
return new WechatSender();
}
return null;
}
}
/**
* @redame 工厂方法模式
*/
public class MessageFactoryB {
public Sender productMail(){
return new MailSender();
}
public Sender productSMS(){
return new SmsSender();
}
public Sender productWechat(){
return new WechatSender();
}
}
结构型模式之【适配器模式】
问题
有时,为复用而设计的工具箱类不能够被复用的原因,仅仅是因为它的接口与专业应用领域所需要的接口不匹配。
解决方案
应用通过适配器调用接口,由适配器使得工具箱类可以被使用。
public class Source {
public void method1(){
System.out.println("一个普通方法实现.");
}
}
public interface Targetable {
//与原类中的方法相同
public void method1();
//新类中的方法
public void method2();
}
/**
* 类适配器
*/
public class SpecialAdapter extends Source implements Targetable {
@Override
public void method2() {
System.out.println("这是一个特殊方法实现.");
}
}
/**
* 对象适配器
*/
public class SpecialAdapter implements Targetable {
/**
* 可匹配Source的子类
**/
private Source source;
public SpecialAdapter(Source source){
super();
this.source = source;
}
@Override
public void method1() {
source.method1();
}
@Override
public void method2() {
System.out.println("这是一个特殊方法实现.");
}
}
public static void main(String[] args) {
//类适配
Targetable target = new SpecialAdapter();
target.method1();
target.method2();
//对象适配
Targetable adapter = new SpecialAdapter(new Source());
adapter.method1();
adapter.method2();
}
结构型模式之【代理模式】
问题
对象的访问需要被控制,不允许其他对象任意访问此对象接口。
解决方案
代理类开放接口提供访问,所有访问由代理类决定具体的调用。
/**
*抽象类
*/
public abstract class AbstractObject {
//代理方法
public abstract void operation();
}
/**
* 代理对象
*/
public class RealObject extends AbstractObject {
@Override
public void operation() {
System.out.println("具体执行任务.");
}
}
/**
* 代理类
*/
public class ProxyObject extends AbstractObject {
//代理对象
RealObject realObject = new RealObject();
@Override
public void operation() {
System.out.println("执行任务前, 做一些什么事情.");
realObject.operation();
}
}
public static void main(String[] args) {
AbstractObject obj = new ProxyObject();
obj.operation();
}
行为模式之【观察者模式】
问题
将一个系统分割成一系列相互协作的类有一个常见的副作用:需要维护相关对象间的一致性,然而维护对象间的一致性可能导致各类之间的紧密耦合,这样将降低它们的可重用性。
解决方案
观察者模式建立一个目标和任意个依赖它的观察者,一旦目标状态发生改变,所有的观察者都得到通知。
public abstract class AbstractSubject implements Subject {
private Vector<Observer> observerList = new Vector<Observer>();
public void add(Observer observer) {
observerList.add(observer);
}
public void del(Observer observer) {
observerList.remove(observer);
}
public void notifyObservers() {
for (Observer observer : observerList) {
observer.update();
}
}
}
public class MySubject extends AbstractSubject {
@Override
public void operation() {
System.out.println("执行方法, 状态修改. ");
notifyObservers();
}
}
public interface Observer {
public void update();
}
public class ObserverA implements Observer {
@Override
public void update() {
System.out.println("观察者A观察到对象的变化.");
}
}
public class ObserverB implements Observer {
@Override
public void update() {
System.out.println("观察者B观察到对象的变化.");
}
}
public static void main(String[] args) {
AbstractSubject subject = new MySubject();
subject.add(new ObserverA());
subject.add(new ObserverB());
subject.operation();
}
=======================运行结果
执行方法, 状态修改.
观察者A观察到对象的变化.
观察者B观察到对象的变化.
行为模式之【策略模式】
问题
开发中常见的情况:实现某功能可以有多种算法或者策略,可根据实际情况选择不同的算法或策略来完成该功能。如果将所有算法或策略都封装在一个类中,提供不同方法来实现,这个类就变得臃肿,而且新增算法或策略时,需要修改封装算法类的源码。
解决方案
使用不同类来封装不同的算法
public interface MemberStrategy {
/**
* 计算图书的价格
* @param booksPrice 图书的原价
* @return 计算出打折后的价格
*/
public double calcPrice(double booksPrice);
}
public class AdvancedMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double booksPrice) {
System.out.println("高级会员8折");
return booksPrice * 0.8;
}
}
public class IntermediateMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double booksPrice) {
System.out.println("中级会员9折");
return booksPrice * 0.9;
}
}
public class PrimaryMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double booksPrice) {
System.out.println("初级会员没有折扣");
return booksPrice;
}
}
public class Price {
//持有一个具体的策略对象
private MemberStrategy strategy;
/**
* @param strategy
*/
public Price(MemberStrategy strategy) {
super();
this.strategy = strategy;
}
/**
* 计算图书的价格
* @param booksPrice 图书的原价
* @return 计算出打折后的价格
*/
public double quote(double booksPrice){
return this.strategy.calcPrice(booksPrice);
}
}
public static void main(String[] args) {
//选择并创建需要使用的策略对象
MemberStrategy strategy = new AdvancedMemberStrategy();
//创建环境
Price price = new Price(strategy);
//计算价格
double quote = price.quote(300);
System.out.println("图书的最终价格为:" + quote);
}
=========运行结果
高级会员8折
图书的最终价格为:240.0