赞
踩
保证一个类仅有一个实例,并提供它的全局访问点
常见写法:
懒汉式
/** * 优点:延迟加载,适合单线程操作 * 缺点:线程不安全,在多线程很容易出现不同步的情况 */ public class Singleton { //持有私有静态实例,防止被引用 private static Singleton instance = null; //私有构造,防止被实例化 private Singleton () {} public static Singleton getInstance() { if (instance==null) { instance = new Singleton(); } return instance; } }
双重线程检查模式
/** * 优点:延迟加载,线程安全 * 缺点:写法复杂,不简洁 */ public class Singleton { private static volatile Singleton sInst = null; //私有构造,防止被实例化 private Singleton () {} public static Singleton getInstance() { //创建临时变量 Singleton inst = sInst; if (inst==null) { synchronized (Singleton.class) { inst = sInst; if (inst==null) { inst = new Singleton(); sInst = inst; } } } return inst; } }
饿汉式
/**
* 优点:延迟加载,线程安全(java中class加载时互斥的),减少了内存小号,推荐使用内部类方式
*/
public class Singleton {
//内部类实现单例,延迟加载,减少内存开销
private static class SingletonHolder {
private static Singleton instance = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
是一种对象构建的设计模式,它可以将负责对象的构建过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象
为何使用
是为了将构建复杂对象的过程和它的部件解耦
如何使用
//需要一个接口,它定义如何创建复杂对象的各个部件 public interface Builder { //创建部件A void buildPartA(); //创建部件B void buildPartB(); //创建部件C void buildPartC(); //从而实现了解耦过程和部件 Product getResult(); } //构建最后的复杂对象 public class Director { private Builder builder; public Director( Builder builder ) { this.builder = builder; } // 将部件partA partB partC最后组成复杂对象 //这里是将车轮 方向盘和发动机组装成汽车的过程 public void construct() { builder.buildPartA(); builder.buildPartB(); builder.buildPartC(); } } //具体实现,明确需要创建的东西 public class ConcreteBuilder implement Builder { Part partA, partB, partC; public void buildPartA() { //具体实现 } public void buildPartB() { //具体实现 } public void buildPartC() { //具体实现 } public Product getResult() { //返回组装结果 } } //复杂对象:产品Product public interface Product{} //复杂对象的部件 public interface Part{} public void main(String[] args) { ConcreteBuilder builder = new ConcreteBuilder(); Director director = new Director(builder); director.construct(); Product product = builder.getResult(); }
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同事监听某一主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。观察者模式又叫发布-订阅(Publish/Subscribe)模式
模式的结构
观察者模式的主要角色如下。
public class ObserverPattern { public static void main(String[] args) { Subject subject=new ConcreteSubject(); Observer obs1=new ConcreteObserver1(); Observer obs2=new ConcreteObserver2(); subject.add(obs1); subject.add(obs2); subject.notifyObserver(); } } //抽象目标 abstract class Subject { protected 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 notifyObserver(); //通知观察者方法 } //具体目标 class ConcreteSubject extends Subject { public void notifyObserver() { System.out.println("具体目标发生改变..."); System.out.println("--------------"); for(Object obs:observers) { ((Observer)obs).response(); } } } //抽象观察者 interface Observer { void response(); //反应 } //具体观察者1 class ConcreteObserver1 implements Observer { public void response() { System.out.println("具体观察者1作出反应!"); } } //具体观察者1 class ConcreteObserver2 implements Observer { public void response() { System.out.println("具体观察者2作出反应!"); } }
何时适用
模式的扩展
在Java中,通过java.util.Observable类和java.util.Observer接口定义了观察者模式,只要实现他们的子类就可以编写观察者模式
/** * @Desc: * @Author: zhouben * @Date:2019/7/3 10:28 */ public class CrudeOilFutures { public static void main(String[] args) { OilFutures oil = new OilFutures(); Observer bull = new Bull(); //多方 Observer bear = new Bear(); //空方 oil.addObserver(bull); oil.addObserver(bear); oil.setPrice(10); oil.setPrice(-8); } } /** * @Desc: 目标类:原油期货 * @Author: zhouben * @Date:2019/7/3 10:23 */ public class OilFutures extends Observable { private float price; public float getPrice() { return price; } public void setPrice(float price) { //设置内部标志位,注明数据发生变化 super.setChanged(); //通知观察者价格变了 super.notifyObservers(price); this.price = price; } } /** * @Desc: 具体观察者:多方 * @Author: zhouben * @Date:2019/7/3 10:25 */ public class Bull implements Observer { @Override public void update(Observable o, Object arg) { float price = ((Float) arg).floatValue(); if (price > 0) { System.out.println("油价上涨"+price+"元,多方高兴了!"); } else { System.out.println("油价下跌"+(-price)+"元,多方伤心了!"); } } } /** * @Desc: 具体观察者:空方 * @Author: zhouben * @Date:2019/7/3 10:25 */ public class Bear implements Observer { @Override public void update(Observable o, Object arg) { float price = ((Float) arg).floatValue(); if (price > 0) { System.out.println("油价上涨"+price+"元,空方伤心了!"); } else { System.out.println("油价下跌"+(-price)+"元,空方高兴了!"); } } }
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法再一起工作时的两个类都能在一起工作
类适配器模式
从上图可以看出,Adaptee类并没有samepleOperation2()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,提供一个中间环节,即类Adapter,把Adaptee的API与target类的API衔接起来
public interface Target { /** * 这是源类Adaptee也有的方法 */ public void sampleOperation1(); /** * 这是源类Adapteee没有的方法 */ public void sampleOperation2(); } public class Adaptee { public void sampleOperation1(){} } public class Adapter extends Adaptee implements Target { /** * 由于源类Adaptee没有方法sampleOperation2() * 因此适配器补充上这个方法 */ @Override public void sampleOperation2() { //写相关的代码 } }
对象适配器模式
从上图可以看出,Adaptee类并没有sampleOperation2()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,需要提供一个包装(Wrapper)类Adapter。这个包装类包装了一个Adaptee的实例,从而此包装类能够把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。
public interface Target { /** * 这是源类Adaptee也有的方法 */ public void sampleOperation1(); /** * 这是源类Adapteee没有的方法 */ public void sampleOperation2(); } public class Adaptee { public void sampleOperation1(){} } public class Adapter { private Adaptee adaptee; public Adapter(Adaptee adaptee){ this.adaptee = adaptee; } /** * 源类Adaptee有方法sampleOperation1 * 因此适配器类直接委派即可 */ public void sampleOperation1(){ this.adaptee.sampleOperation1(); } /** * 源类Adaptee没有方法sampleOperation2 * 因此由适配器类需要补充此方法 */ public void sampleOperation2(){ //写相关的代码 } }
装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些指责(即增加其额外功能)的模式,它属于对象结构型模式
优点:
缺点: 增加了许多子类,过度使用会使程序变得复杂
模式的结构
装饰模式的结构图:
模式的实现
public class MorriganAensland { public static void main(String[] args) { Morrigan m0 = new Original(); m0.display(); Morrigan m1 = new Succubus(m0); m1.display(); Morrigan m2 = new Girl(m0); m2.display(); } } /** * 抽象构件角色 */ public interface Morrigan { public void display(); } /** * @Desc: 具体构件角色 * @Author: zhouben * @Date:2019/7/2 10:19 */ public class Original extends JFrame implements Morrigan { private String t = "Morrigan0.jpg"; public Original() { super("《恶魔战士》中的莫莉卡·安斯兰"); } public void setImage(String t) { this.t = t; } @Override public void display() { /*this.setLayout(new FlowLayout()); JLabel l1=new JLabel(new ImageIcon("com/zben/decorator/"+t)); this.add(l1); this.pack(); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true);*/ System.out.println("具体构件角色....Morrigan0.jpg"); } } /** * @Desc: 抽象装饰角色 * @Author: zhouben * @Date:2019/7/2 10:24 */ public class Changer implements Morrigan { Morrigan m; public Changer(Morrigan m) { this.m = m; } @Override public void display() { m.display(); } } /** * @Desc: 具体装饰角色:女妖 * @Author: zhouben * @Date:2019/7/2 10:26 */ public class Succubus extends Changer { public Succubus(Morrigan m) { super(m); } @Override public void display() { setChanger(); super.display(); } private void setChanger() { ((Original)super.m).setImage("Morrigan1.jpg"); System.out.println("Morrigan1"); } } /** * @Desc: 具体装饰角色:少女 * @Author: zhouben * @Date:2019/7/2 10:26 */ public class Girl extends Changer { public Girl(Morrigan m) { super(m); } @Override public void display() { setChanger(); super.display(); } private void setChanger() { ((Original)super.m).setImage("Morrigan2.jpg"); System.out.println("Morrigan2"); } }
代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为对象和目标对象之间的中介
优点:
缺点
模式的结构
抽象主题(Subject):通过接口或抽象类声明真实主题和代理对象实现的业务方法
真实主题(RealSubject):实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
代理(Proxy):提供了与真实主题相同的接口,其内部含有对真实主题的引用
模式的实现
public class WySpecialProxy { public static void main(String[] args) { Sgproxy sgproxy = new Sgproxy(); sgproxy.display(); } } /** * 抽象主题 */ public interface Specialty { public void display(); } /** * @Desc: 真实主题 * @Author: zhouben * @Date:2019/7/2 11:28 */ public class WySpecialty extends JFrame implements Specialty { public WySpecialty() { super("韶关代理婺源特产测试"); this.setLayout(new GridLayout(1,1)); JLabel l1=new JLabel(new ImageIcon("D:\\idea-project\\test\\java-design\\src\\main\\resources\\WuyuanSpecialty.jpg")); this.add(l1); this.pack(); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } @Override public void display() { this.setVisible(true); } } /** * @Desc:代理类 * @Author: zhouben * @Date:2019/7/2 11:31 */ public class Sgproxy implements Specialty { private WySpecialty realSubject=new WySpecialty(); @Override public void display() { preRequest(); realSubject.display(); postRequest(); } public void preRequest() { System.out.println("韶关代理婺源开始。。。"); } public void postRequest() { System.out.println("韶关代理婺源结束。。。"); } }
定义
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的心对象。
模式的结构
public class ProtoTypeCitation { public static void main(String[] args) throws CloneNotSupportedException { Citation obj1 = new Citation("张三", "同学:在2016学年第一学期中表现优秀,被评为三好学生。","韶关学院"); obj1.display(); Citation obj2 = (Citation)obj1.clone(); obj2.setName("李四"); obj2.display(); } } public class Citation implements Cloneable { private String name; private String info; private String college; public Citation(String name, String info, String college) { this.name = name; this.info = info; this.college = college; System.out.println("奖状创建成功!"); } public void display() { System.out.println(name + info + college); } @Override protected Object clone() throws CloneNotSupportedException { System.out.println("奖状拷贝成功!"); return (Citation)super.clone(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } public String getCollege() { return college; } public void setCollege(String college) { this.college = college; } }
原型模式的应用场景
定义:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤
优点
模式的结构
/** * @Desc: 用模板方法模式实现出国留学手续设计程序。 * 分析:出国留学手续一般经过以下流程:索取学校资料,提出入学申请,办理因私出国护照、出境卡和公证,申请签证, * 体检、订机票、准备行装,抵达目标学校等,其中有些业务对各个学校是一样的,但有些业务因学校不同而不同, * 所以比较适合用模板方法模式来实现。 * @Author: zhouben * @Date:2019/7/2 14:44 */ public class StudyAbroadProcess { public static void main(String[] args) { StudyAbroad studyAbroad = new StudyInAmerica(); studyAbroad.templateMethod(); } } /** * @Desc: 抽象类:出国留学 * @Author: zhouben * @Date:2019/7/2 14:35 */ public abstract class StudyAbroad { //模板方法 public void templateMethod() { lookingForSchool(); //索取学校资料 applyForEnrol(); //入学申请 applyForPassport(); //办理因私出国护照、出境卡和公证 applyForVisa(); //申请签证 readyGoAbroad(); //体检、订机票、准备出行 arriving(); //抵达 } protected abstract void arriving(); protected abstract void applyForEnrol(); protected abstract void lookingForSchool(); private void readyGoAbroad() { System.out.println("五.体检、订机票、准备行装:"); System.out.println(" 1)进行身体检查、免疫检查和接种传染病疫苗;"); System.out.println(" 2)确定机票时间、航班和转机地点。"); } private void applyForVisa() { System.out.println("四.申请签证:"); System.out.println(" 1)准备申请国外境签证所需的各种资料,包括个人学历、成绩单、工作经历的证明;个人及家庭收入、资金和财产证明;家庭成员的关系证明等;"); System.out.println(" 2)向拟留学国家驻华使(领)馆申请入境签证。申请时需按要求填写有关表格,递交必需的证明材料,缴纳签证。有的国家(比如美国、英国、加拿大等)在申请签证时会要求申请人前往使(领)馆进行面试。"); } private void applyForPassport() { System.out.println("三.办理因私出国护照、出境卡和公证:"); System.out.println(" 1)持录取通知书、本人户口簿或身份证向户口所在地公安机关申请办理因私出国护照和出境卡。"); System.out.println(" 2)办理出生公证书,学历、学位和成绩公证,经历证书,亲属关系公证,经济担保公证。"); } } /** * @Desc:具体子类:美国留学 * @Author: zhouben * @Date:2019/7/2 14:43 */ public class StudyInAmerica extends StudyAbroad { @Override protected void arriving() { System.out.println("六.抵达目标学校:"); System.out.println(" 1)安排住宿;"); System.out.println(" 2)了解校园及周边环境。"); } @Override protected void applyForEnrol() { System.out.println("二.入学申请:"); System.out.println(" 1)填写报名表;"); System.out.println(" 2)将报名表、个人学历证明、最近的学习成绩单、推荐信、个人简历、托福或雅思语言考试成绩单等资料寄往所申请的学校;"); System.out.println(" 3)为了给签证办理留有充裕的时间,建议越早申请越好,一般提前1年就比较从容。"); } @Override protected void lookingForSchool() { System.out.println("一.索取学校以下资料:"); System.out.println(" 1)对留学意向国家的政治、经济、文化背景和教育体制、学术水平进行较为全面的了解;"); System.out.println(" 2)全面了解和掌握国外学校的情况,包括历史、学费、学制、专业、师资配备、教学设施、学术地位、学生人数等;"); System.out.println(" 3)了解该学校的住宿、交通、医疗保险情况如何;"); System.out.println(" 4)该学校在中国是否有授权代理招生的留学中介公司?"); System.out.println(" 5)掌握留学签证情况;"); System.out.println(" 6)该国政府是否允许留学生合法打工?"); System.out.println(" 8)毕业之后可否移民?"); System.out.println(" 9)文凭是否受到我国认可?"); } }
定义:策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法实现分割开来,并委派给不同的对象对这些算法进行管理
优点:
模式的结构
/** * @Desc:策略模式在“大闸蟹”做菜中的应用。 * * 分析:关于大闸蟹的做法有很多种,我们以清蒸大闸蟹和红烧大闸蟹两种方法为例,介绍策略模式的应用。 * @Author: zhouben * @Date:2019/7/2 17:28 */ public class StrategyMain { public static void main(String[] args) { Kitchen kitchen = new Kitchen(new BraisedCrabs()); kitchen.cookingMethod(); } } /** * 抽象策略: */ public interface CrabCooking { //做菜方法 public void cookingMethod(); } /** * @Desc: 具体策略类:红烧大闸蟹 * @Author: zhouben * @Date:2019/7/2 17:24 */ public class BraisedCrabs implements CrabCooking { @Override public void cookingMethod() { System.out.println("红烧大闸蟹"); } } /** * @Desc: 具体策略类:清蒸大闸蟹 * @Author: zhouben * @Date:2019/7/2 17:24 */ public class SteamedCrabs implements CrabCooking { @Override public void cookingMethod() { System.out.println("清蒸大闸蟹"); } } /** * @Desc: 环境类:厨房 * @Author: zhouben * @Date:2019/7/2 17:25 */ public class Kitchen { private CrabCooking strategy; //抽象策略 public Kitchen(CrabCooking strategy) { this.strategy = strategy; } public void cookingMethod() { strategy.cookingMethod(); } public CrabCooking getStrategy() { return strategy; } public void setStrategy(CrabCooking strategy) { this.strategy = strategy; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。