何为模式
经常使用的方案,公认为正确或相对正确
何为设计模式
一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结
设计模式分类
创建型模式
•简单工厂模式
•工厂方法模式
•抽象工厂模式
•建造者模式
•原型模式
结构型模式
•外观模式
•适配器模式
•装饰模式
•桥接模式
•组合模式
•享元模式
行为型模式
•观察者模式
•状态模式
•策略模式
•职责链模式
•命令模式
•中介者模式
•备忘录模式
•迭代器模式
设计模式详解
简单工厂模式
•定义:
–根据输入或上下文选择创建哪种对象。
•场景与功用:
–将对象的创建与使用分离
–集中处理共通创建步骤
•样例代码:
package simplefactory; class BaseView { } abstract class PicView extends BaseView { } abstract class VideoView extends BaseView { } class FeedPicView extends PicView { } class FeedVideoView extends VideoView { } class FeedFactory { public static BaseView createView(String type) { switch (type) { case "pic" : return new FeedPicView(); case "video" : return new FeedVideoView(); } return null ; } } public class SimpleFactoryDemo { public static void main(String[] args) { BaseView picView = FeedFactory.createView( "pic" ); BaseView videoView = FeedFactory.createView( "video" ); System.out.println(picView.getClass().getSimpleName() + " " + videoView.getClass().getSimpleName()); } } |
工厂方法模式
•定义:
–定义一个用于创建对象的接口,让子类决定实例化哪一个类。
•场景与功用:
–使一个类的实例化延迟到其子类
–通过选择子工厂来生产对应的对象
–将对象的创建与使用分离
–抽象共通创建步骤
•样例代码:
package factorymethod; class BaseView { } abstract class PicView extends BaseView { } abstract class VideoView extends BaseView { } class FeedPicView extends PicView { } class FeedVideoView extends VideoView { } abstract class ViewFactory { abstract public BaseView createView(); } class PicFactory extends ViewFactory { @Override public BaseView createView() { return new FeedPicView(); } } class VideoFactory extends ViewFactory { @Override public BaseView createView() { return new FeedVideoView(); } } public class FactoryMethodDemo { public static void main(String[] args) { BaseView picView = new PicFactory().createView(); BaseView videoView = new VideoFactory().createView(); System.out.println(picView.getClass().getSimpleName() + " " + videoView.getClass().getSimpleName()); } } |
抽象工厂方法
•定义:
–提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
•场景与功用:
–两种以上产品系列
–系列之间,产品的种数相同、抽象相同
–将对象的创建与使用分离
–抽象共通创建步骤
•样例代码:
package abstractfactory; class BaseView { } abstract class PicView extends BaseView { } abstract class VideoView extends BaseView { } class FeedPicView extends PicView { } class FeedVideoView extends VideoView { } class RecommendPicView extends PicView { } class RecommendVideoView extends VideoView { } abstract class ViewFactory { abstract PicView createPicView(); abstract VideoView createVideoView(); } class FeedViewFactory extends ViewFactory { @Override PicView createPicView() { return new FeedPicView(); } @Override VideoView createVideoView() { return new FeedVideoView(); } } class RecommendViewFactory extends ViewFactory { @Override PicView createPicView() { return new RecommendPicView(); } @Override VideoView createVideoView() { return new RecommendVideoView(); } } public class AbstractFactoryDemo { public static void main(String[] args) { // 在feed列表中 displayViews( new FeedViewFactory()); // 在recommend列表中 displayViews( new RecommendViewFactory()); } public static void displayViews(ViewFactory factory) { PicView picView = factory.createPicView(); VideoView videoView = factory.createVideoView(); System.out.println(picView.getClass().getSimpleName() + " " + videoView.getClass().getSimpleName()); } } |
建造者模式
•定义:
–将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示
–表示可以理解为实现方式
•场景与功用
–算法实现方式与对象构造过程无关
–构造过程的抽象
•样例代码:
package builder; import android.net.Uri; public class BuilderDemo { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append( "This " ); sb.append( "is " ); sb.append( "a " ); sb.append( "demo " ); sb.append( "for " ); sb.append( "Builder." ); System.out.println(sb.toString()); } public static void uriBuilderDemo(){ Uri.Builder ub = new Uri.Builder(); ub.scheme( "http" ); ub.authority( "api.sina.com:8080" ); ub.appendPath( "list.json" ); ub.appendQueryParameter( "wm" , "0560" ); System.out.println(ub.build().toString()); } } |
原型模式
•定义:
–用原型对象指定创建对象的种类,并且通过拷贝这些原型对象创建新的对象
–又名“克隆模式”
•场景与功用:
–需要创建一个初始化代价较大的对象
–类自己决定哪些字段深拷贝哪些浅拷贝
•样例代码:
package prototype; import java.util.ArrayList; class NewsItem implements Cloneable { private String id = "" ; private String title = "" ; private String source = "" ; private String link = "" ; private int comment; private String category = "" ; private ArrayList<String> pv = new ArrayList<String>(); private ArrayList<String> monitor = new ArrayList<String>();; @Override public NewsItem clone() throws CloneNotSupportedException { NewsItem obj = (NewsItem) super .clone(); obj.pv = (ArrayList<String>) pv.clone(); obj.monitor = (ArrayList<String>) monitor.clone(); return obj; } } class VideoNewsItem implements Cloneable { private VideoInfo video_info = new VideoInfo(); @Override public VideoNewsItem clone() throws CloneNotSupportedException { VideoNewsItem item = (VideoNewsItem) super .clone(); item.video_info = video_info.clone(); return item; } } class VideoInfo implements Cloneable { private String pic = "" ; private String url = "" ; private String runtime = "" ; private String playnumber = "" ; private String type = "" ; @Override public VideoInfo clone() throws CloneNotSupportedException { return (VideoInfo) super .clone(); } } public class PrototypeDemo { public static void main(String[] args) throws CloneNotSupportedException { VideoNewsItem item1 = new VideoNewsItem(); VideoNewsItem item2 = item1.clone(); System.out.println(item1==item2); } } |
外观模式
•定义:
–为子系统中的一组接口提供一个一致的界面
•场景与功用
–调用旧系统或第三方系统
–调用接口繁杂的系统
–将常用子接口组合封装成为简单的新接口
适配器模式
•定义:
–将一个类的接口转换成使用者希望的接口形式
•分类:
–类适配器:继承适配
–对象适配器:委托适配
•场景:
–两个系统接口不兼容时
–双方系统都不易或不能修改时
装饰模式
•定义:
–动态地给一个对象添加一些额外的职责。
•场景与功用:
–将类的核心职能和额外的装饰功能分离,并且可以随意重用或选用装饰逻辑。
•样例代码:
package decorator; interface Number { public String getNumber(); } class PhoneNumber implements Number { private String number; public PhoneNumber(String number) { this .number = number; } @Override public String getNumber() { return number; } } class CityDecorator implements Number { private Number number; public CityDecorator(Number number) { this .number = number; } @Override public String getNumber() { return "010-" + number.getNumber(); } } class NationDecorator implements Number { private Number number; public NationDecorator(Number number) { this .number = number; } @Override public String getNumber() { return "+86-" + number.getNumber(); } } class AsteriskDecorator implements Number { private Number number; public AsteriskDecorator(Number number) { this .number = number; } @Override public String getNumber() { return "***" + number.getNumber() + "***" ; } } public class DecoratorDemo { public static void main(String[] args) { Number number = null ; //////////////////////////////// number = new PhoneNumber( "82675588" ); number = new CityDecorator(number); number = new NationDecorator(number); number = new AsteriskDecorator(number); System.out.println(number.getNumber()); //////////////////////////////// number = new PhoneNumber( "82675588" ); number = new CityDecorator(number); number = new AsteriskDecorator(number); System.out.println(number.getNumber()); //////////////////////////////// number = new PhoneNumber( "82675588" ); number = new AsteriskDecorator(number); number = new CityDecorator(number); System.out.println(number.getNumber()); } } |
桥接模式
•定义:
–将抽象部分与它的实现部分分离,使它们都可以独立地变化。
•组合/聚合复用原则:
–尽量使用组合/聚合,而不是使用类继承
•场景与功用
–一个抽象出现了多个维度的变化
–控制类爆炸,以减弱维度间的耦合
•样例代码:
不使用桥接
package bridge; import com.sina.news.R; import com.sina.news.bean.NewsItem; class PicNewsItem extends NewsItem { //category = "cms"; public int getIcon() { return - 1 ; } } class VideoNewsItem extends NewsItem { //category = "video"; public int getIcon() { return R.drawable.ic_list_item_video_normal; } } class RecommendPicNewsItem extends NewsItem { //category = "cms"; public int getIcon() { return - 1 ; } } class RecommendVideoNewsItem extends NewsItem { //category = "video"; public int getIcon() { return R.drawable.ic_list_item_video_normal; } } public class NonBridgeDemo { public static void main(String[] args) { } } |
使用桥接
package bridge; import com.sina.news.R; import com.sina.news.bean.NewsItem; abstract class Category { abstract public int getIcon(); } class PicCategory extends Category { @Override public int getIcon() { return - 1 ; } } class VideoCategory extends Category { @Override public int getIcon() { return R.drawable.ic_list_item_video_normal; } } class NormalNewsItem extends NewsItem { // Category category = new PicCategory(); Category category = new VideoCategory(); } class RecommendNewsItem extends NewsItem { Category category = new PicCategory(); // Category category = new VideoCategory(); } public class BridgeDemo { public static void main(String[] args) { } } |
组合模式
•定义:
–将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
•场景与功用
–需要树形数据结构时
–树枝与树叶没有区别,使用时可以一致对待
•样例代码:
package composite; import java.util.ArrayList; import java.util.Collection; import java.util.List; class View { } class ViewGroup extends View { private List<View> children = new ArrayList<View>(); public void add(View v) { children.add(v); } public Collection<View> getChildren() { return new ArrayList<View>(children); } } public class CompositeDemo { public static void main(String[] args) { ViewGroup vg1 = new ViewGroup(); ViewGroup vg2 = new ViewGroup(); ViewGroup vg3 = new ViewGroup(); ViewGroup vg4 = new ViewGroup(); ViewGroup vg5 = new ViewGroup(); // @formatter:off /* vg1 * |--vg2 * | |--vg4 * | |--vg5 * | * |--vg3 */ // @formatter:on vg1.add(vg2); vg1.add(vg3); vg2.add(vg4); vg2.add(vg5); } } |
享元模式
•定义:
–运用共享技术有效地支持大量细粒度的对象。
•场景与功用:
–同一时段使用不多,而总体数量庞大的可共享对象
•可共享对象:
–初始化代价较大(内部状态)
–可变属性较少(外部状态)
观察者模式
•定义:
–定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
•场景与功用
–对象联动,一个对象改变同时需要更新其他对象
–对象定义时不知道有多少对象有待改变
•样例代码:
package observer; import java.util.Observable; import java.util.Observer; public class ObserverDemo { public static int SHARE_TYPE_NORMAL = 1 ; public static int SHARE_TYPE_EXCLUSIVE = 2 ; private CheckBox mCheckboxEnable = new CheckBox(); private SelectBox mSelectShareType = new SelectBox(); private TextBox mTextShareName = new TextBox(); private CheckBox mCheckboxReadOnly = new CheckBox(); private Label mLabelDescrpiton = new Label(); abstract class View extends Observable implements Observer { private boolean disabled = false ; public void setDisabled( boolean disabled) { this .disabled = disabled; } public boolean isDisabled() { return this .disabled; } } class SelectBox extends View { private int selected; public void setSelect( int index) { this .selected = index; setChanged(); notifyObservers(); } public int getSelect() { return selected; } @Override public void update(Observable observable, Object data) { if (mCheckboxEnable.isChecked()) { this .setDisabled( true ); } else { this .setDisabled( false ); } } } class TextBox extends View { private String text; public void setText(String text) { this .text = text; setChanged(); notifyObservers(); } public String getText() { return text; } @Override public void update(Observable observable, Object data) { if (mCheckboxEnable.isChecked()) { this .setDisabled( true ); } else { this .setDisabled( false ); } } } class CheckBox extends View { private boolean checked; public void setChecked( boolean checked) { this .checked = checked; setChanged(); notifyObservers(); } public boolean isChecked() { return checked; } @Override public void update(Observable observable, Object data) { if ( this == mCheckboxEnable) { return ; } if ( this == mCheckboxReadOnly) { if (mSelectShareType.getSelect() == SHARE_TYPE_NORMAL) { this .setDisabled( false ); } else if (mSelectShareType.getSelect() == SHARE_TYPE_EXCLUSIVE) { this .setChecked( true ); this .setDisabled( true ); } } } } class Label extends View { private String text; @Override public void update(Observable observable, Object data) { if (!mCheckboxEnable.isChecked()) { this .text = "Disabled" ; return ; } this .text = mSelectShareType.toString() + mTextShareName.toString() + mCheckboxReadOnly.toString(); } public String getText() { return text; } } public ObserverDemo() { mCheckboxEnable.addObserver(mSelectShareType); mCheckboxEnable.addObserver(mTextShareName); mCheckboxEnable.addObserver(mCheckboxReadOnly); mCheckboxEnable.addObserver(mLabelDescrpiton); mSelectShareType.addObserver(mCheckboxReadOnly); mSelectShareType.addObserver(mLabelDescrpiton); mTextShareName.addObserver(mCheckboxReadOnly); mTextShareName.addObserver(mLabelDescrpiton); } public static void main(String[] args) { } } |
状态模式
•定义:
–当一个对象的内在状态改变时,允许改变其行为,这个对象看起来是改变了其类。
•场景与功用
–控制一个对象状态转换的条件过于复杂
–把状态转换逻辑封装到一系列类中,将逻辑局部化
–降低状态之间的耦合
•样例代码:
package state; class Activity { protected State state; abstract class State { abstract void next(); } class BootImageState extends State { @Override void next() { if (isFirstRun()) { state = new FinishState(); } else { showBootImage(); state = new AdState(); } } } class AdState extends State { @Override void next() { if (isAdReady()) { showAd(); state = new FinishState(); } else { state = new CoverStoryState(); } } } class CoverStoryState extends State { @Override void next() { if (isCoverStoryReady()) { showCoverStory(); } state = new FinishState(); } } class FinishState extends State { @Override void next() { state = null ; enterMainActivity(); } } private boolean isFirstRun() { return false ; } private void showBootImage(){} private boolean isAdReady() { return true ; } private void showAd() { } private boolean isCoverStoryReady() { return true ; } private void showCoverStory() { } public void enterMainActivity() { // MainActivity.start(); // this.finish(); } public void execute() { while (state != null ) { state.next(); } } } public class StateDemo { public static void main(String[] args) { Activity powerOn = new Activity(); powerOn.execute(); } } |
策略模式
•定义:
–定义算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法使用者可以不改变实现的情况下灵活切换算法。
•场景与功用:
–减少了算法使用者与算法之间的耦合
•扩展:
–可以封装任何类型的变化
•样例代码:
package strategy; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; class Person { private final int id; private final String name; public Person( int id, String name) { this .id = id; this .name = name; } public int getId() { return id; } public String getName() { return name; } public String toString() { return "{" + id + ", " + name + "}" ; } } class PersonComparatorById implements Comparator<Person> { @Override public int compare(Person p0, Person p1) { return p0.getId() - p1.getId(); } } class PersonComparatorByName implements Comparator<Person> { @Override public int compare(Person p0, Person p1) { return p0.getName().compareTo(p1.getName()); } } public class StrategyDemo { public static void main(String[] args) { List<Person> persons = Arrays.asList( new Person( 80 , "Mick" ), new Person( 90 , "Racheal" ), new Person( 15 , "Jack" ), new Person( 21 , "Don" ), new Person( 93 , "Wislee" ), new Person( 65 , "Lucy" ), new Person( 70 , "Nazu" )); Collections.sort(persons, new PersonComparatorById()); System.out.println( "Sorted by ID : " + persons); Collections.sort(persons, new PersonComparatorByName()); System.out.println( "Sorted by Name : " + persons); } } |
职责链模式
•定义:
–将请求的可能接收者组织成链,让请求延这条链传递直到有一个接收者处理它为止。
•相关概念:
–AOP:面向切片编程
•场景与功用
–请求处理逻辑经常变化的场合
–各处理逻辑之间解耦合
•样例代码:
package responsibilitychain; import android.content.Intent; import android.net.ConnectivityManager; abstract class IntentHandler { private final IntentHandler nextHandler; public IntentHandler(IntentHandler nextHandler) { this .nextHandler = nextHandler; } abstract public boolean process(Intent intent); public void handle(Intent intent) { if (process(intent) && nextHandler != null ) { nextHandler.process(intent); } } } class ActionValidateHandler extends IntentHandler { public ActionValidateHandler(IntentHandler nextHandler) { super (nextHandler); } @Override public boolean process(Intent intent) { if (intent.getAction() == null ) { return false ; } return true ; } } class NetworkChangeHandler extends IntentHandler { public NetworkChangeHandler(IntentHandler nextHandler) { super (nextHandler); } @Override public boolean process(Intent intent) { if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { // 处理网络变化逻辑 } return true ; } } class SaveIntentHandler extends IntentHandler { public SaveIntentHandler(IntentHandler nextHandler) { super (nextHandler); } @Override public boolean process(Intent intent) { save((Intent) intent.clone()); return true ; } private void save(Intent intent) { // 保存intent } } class Receiver { public void receive(Intent intent) { IntentHandler saveHandler = new SaveIntentHandler( null ); IntentHandler netHandler = new NetworkChangeHandler(saveHandler); IntentHandler actionHandler = new ActionValidateHandler(netHandler); actionHandler.handle(intent); } } public class ChainOfResponsibilityDemo { public static void main(String[] args) { new Receiver().receive( new Intent()); } } |
命令模式
•定义:
–将一个请求(命令)封装成一个对象,从而可用不同的请求对客户端进行参数化。
•场景与功用
–多方请求容易冲突的场合
–请求可以排队,记录日志,重做以及撤销
中介者模式
•定义:
–用一个中介对象来封装一系列对象的交互。
•场景与功用:
–各对象不需要显式地相互引用,独立变化互不干涉,降低耦合
备忘录模式
•定义:
–在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。
•场景与功用
–功能比较复杂,但需要维护或记录属性历史的类
–需要保存的属性只是部分属性,用原型模式的代价过大时
迭代器模式
•定义:
–提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
•场景与功用
–自定义聚合数据
–封装聚合数据的内部实现,与使用者的数据结构解耦合
•样例代码:
package iterator; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import com.sina.news.bean.NewsItem; class NewsItemList implements Iterable<NewsItem> { private List<NewsItem> items = null ; public NewsItemList() { items = new ArrayList<NewsItem>(); } public void add(NewsItem item) { items.add(item); } public void addAll(Collection<NewsItem> c) { items.addAll(c); } @Override public Iterator<NewsItem> iterator() { return new Iterator<NewsItem>() { private int index = - 1 ; @Override public boolean hasNext() { return index + 1 < items.size(); } @Override public NewsItem next() { return items.get(++index); } @Override public void remove() { items.remove(index); } }; } } public class IteratorDemo { public static void main(String[] args) { NewsItemList itemList = new NewsItemList(); itemList.add( new NewsItem()); itemList.add( new NewsItem()); itemList.add( new NewsItem()); itemList.add( new NewsItem()); itemList.add( new NewsItem()); Iterator<NewsItem> it = itemList.iterator(); while (it.hasNext()) { System.out.println(it.next().hashCode()); } // for(NewsItem item : itemList){ // System.out.println(item.hashCode()); // } } } |