设计模式 学习 2:

六个创建型模式

简单工厂:

问题: Sunny软件公司欲基于Java语言开发一套图表库,该图表库可以为应用系统提供各种不同外观的图表,例如柱状图、饼状图、折线图等。Sunny软件公司图表库设计人员希望为应用系统开发人员提供一套灵活易用的图表库,而且可以较为方便地对图表库进行扩展,以便能够在将来增加一些新类型的图表。

//抽象图表接口:抽象产品类

interface Chart {

public void display();

}

//柱状图类:具体产品类

class HistogramChart implements Chart {

public HistogramChart() {

System.out.println("创建柱状图!");

}

public void display() {

System.out.println("显示柱状图!");

}

}

//饼状图类:具体产品类

class PieChart implements Chart {

public PieChart() {

System.out.println("创建饼状图!");

}

public void display() {

System.out.println("显示饼状图!");

}

}

//折线图类:具体产品类

class LineChart implements Chart {

public LineChart() {

System.out.println("创建折线图!");

}

public void display() {

System.out.println("显示折线图!");

}

}

//图表工厂类:工厂类

class ChartFactory {

//静态工厂方法

public static Chart getChart(String type) {

Chart chart = null;

if (type.equalsIgnoreCase("histogram")) {

chart = new HistogramChart();

System.out.println("初始化设置柱状图!");

}

else if (type.equalsIgnoreCase("pie")) {

chart = new PieChart();

System.out.println("初始化设置饼状图!");

}

else if (type.equalsIgnoreCase("line")) {

chart = new LineChart();

System.out.println("初始化设置折线图!");

}

return chart;

}

}

方案的改进

Sunny软件公司开发人员发现在创建具体Chart对象时,每更换一个Chart对象都需要修改客户端代码中静态工厂方法的参数,客户端代码将要重新编译,这对于客户端而言,违反了“开闭原则”,有没有一种方法能够在不修改客户端代码的前提下更换具体产品对象呢?答案是肯定的,下面将介绍一种常用的实现方式。

我们可以将静态工厂方法的参数存储在XML或properties格式的配置文件中,如下config.xml所示:

  1. <?xml version="1.0"?>
  2. <config>
  3. <chartType>histogram</chartType>
  4. </config>

再通过一个工具类XMLUtil来读取配置文件中的字符串参数,XMLUtil类的代码如下所示:

  1. import javax.xml.parsers.*;
  2. import org.w3c.dom.*;
  3. import org.xml.sax.SAXException;
  4. import java.io.*;
  5. public class XMLUtil {
  6. //该方法用于从XML配置文件中提取图表类型,并返回类型名
  7. public static String getChartType() {
  8. try {
  9. //创建文档对象
  10. DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
  11. DocumentBuilder builder = dFactory.newDocumentBuilder();
  12. Document doc;
  13. doc = builder.parse(new File("config.xml"));
  14. //获取包含图表类型的文本节点
  15. NodeList nl = doc.getElementsByTagName("chartType");
  16. Node classNode = nl.item(0).getFirstChild();
  17. String chartType = classNode.getNodeValue().trim();
  18. return chartType;
  19. }
  20. catch(Exception e) {
  21. e.printStackTrace();
  22. return null;
  23. }
  24. }
  25. }

在引入了配置文件和工具类XMLUtil之后,客户端代码修改如下:

  1. class Client {
  2. public static void main(String args[]) {
  3. Chart chart;
  4. String type = XMLUtil.getChartType(); //读取配置文件中的参数
  5. chart = ChartFactory.getChart(type); //创建产品对象
  6. chart.display();
  7. }
  8. }

不难发现,在上述客户端代码中不包含任何与具体图表对象相关的信息,如果需要更换具体图表对象,只需修改配置文件config.xml,无须修改任何源代码,符合“开闭原则”。

多工厂模式

问题:  Sunny软件公司欲开发一个系统运行日志记录器(Logger),该记录器可以通过多种途径保存系统的运行日志,如通过文件记录或数据库记录,用户可以通过修改配置文件灵活地更换日志记录方式。在设计各类日志记录器时,Sunny公司的开发人员发现需要对日志记录器进行一些初始化工作,初始化参数的设置过程较为复杂,而且某些参数的设置有严格的先后次序,否则可能会发生记录失败。如何封装记录器的初始化过程并保证多种记录器切换的灵活性是Sunny公司开发人员面临的一个难题。

简单工厂实际上也违反了开闭原则,如果又增加了一种 实现类,需要修改工场类的逻辑。

//日志记录器接口:抽象产品

interface Logger {

public void writeLog();

}

//数据库日志记录器:具体产品

class DatabaseLogger implements Logger {

public void writeLog() {

System.out.println("数据库日志记录。");

}

}

//文件日志记录器:具体产品

class FileLogger implements Logger {

public void writeLog() {

System.out.println("文件日志记录。");

}

}

//日志记录器工厂接口:抽象工厂

interface LoggerFactory {

public Logger createLogger();

}

//数据库日志记录器工厂类:具体工厂

class DatabaseLoggerFactory implements LoggerFactory {

public Logger createLogger() {

//连接数据库,代码省略

//创建数据库日志记录器对象

Logger logger = new DatabaseLogger();

//初始化数据库日志记录器,代码省略

return logger;

}

}

//文件日志记录器工厂类:具体工厂

class FileLoggerFactory implements LoggerFactory {

public Logger createLogger() {

//创建文件日志记录器对象

Logger logger = new FileLogger();

//创建文件,代码省略

return logger;

}

}

class Client {

public static void main(String args[]) {

LoggerFactory factory;

Logger logger;

factory = new FileLoggerFactory(); //可引入配置文件实现

logger = factory.createLogger();

logger.writeLog();

}

}

新问题:  为了让系统具有更好的灵活性和可扩展性,Sunny公司开发人员决定对日志记录器客户端代码进行重构,使得可以在不修改任何客户端代码的基础上更换或增加新的日志记录方式。

Sunny公司开发人员创建了如下XML格式的配置文件config.xml用于存储具体日志记录器工厂类类名:

  1. <!— config.xml -->
  2. <?xml version="1.0"?>
  3. <config>
  4. <className>FileLoggerFactory</className>
  5. </config>

为了读取该配置文件并通过存储在其中的类名字符串反射生成对象,Sunny公司开发人员开发了一个名为XMLUtil的工具类,其详细代码如下所示:

  1. //工具类XMLUtil.java
  2. import javax.xml.parsers.*;
  3. import org.w3c.dom.*;
  4. import org.xml.sax.SAXException;
  5. import java.io.*;
  6. public class XMLUtil {
  7. //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
  8. public static Object getBean() {
  9. try {
  10. //创建DOM文档对象
  11. DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
  12. DocumentBuilder builder = dFactory.newDocumentBuilder();
  13. Document doc;
  14. doc = builder.parse(new File("config.xml"));
  15. //获取包含类名的文本节点
  16. NodeList nl = doc.getElementsByTagName("className");
  17. Node classNode=nl.item(0).getFirstChild();
  18. String cName=classNode.getNodeValue();
  19. //通过类名生成实例对象并将其返回
  20. Class c=Class.forName(cName);
  21. Object obj=c.newInstance();
  22. return obj;
  23. }
  24. catch(Exception e) {
  25. e.printStackTrace();
  26. return null;
  27. }
  28. }
  29. }

有了XMLUtil类后,可以对日志记录器的客户端代码进行修改,不再直接使用new关键字来创建具体的工厂类,而是将具体工厂类的类名存储在XML文件中,再通过XMLUtil类的静态工厂方法getBean()方法进行对象的实例化,代码修改如下:

  1. class Client {
  2. public static void main(String args[]) {
  3. LoggerFactory factory;
  4. Logger logger;
  5. factory = (LoggerFactory)XMLUtil.getBean(); //getBean()的返回类型为Object,需要进行强制类型转换
  6. logger = factory.createLogger();
  7. logger.writeLog();
  8. }
  9. }

问题2 : Sunny公司开发人员通过进一步分析,发现可以通过多种方式来初始化日志记录器,例如可以为各种日志记录器提供默认实现;还可以为数据库日志记录器提供数据库连接字符串,为文件日志记录器提供文件路径;也可以将参数封装在一个Object类型的对象中,通过Object对象将配置参数传入工厂类。此时,可以提供一组重载的工厂方法,以不同的方式对产品对象进行创建。当然,对于同一个具体工厂而言,无论使用哪个工厂方法,创建的产品类型均要相同

interface LoggerFactory {

public Logger createLogger();

public Logger createLogger(String args);

public Logger createLogger(Object obj);

}

class DatabaseLoggerFactory implements LoggerFactory {

public Logger createLogger() {

//使用默认方式连接数据库,代码省略

Logger logger = new DatabaseLogger();

//初始化数据库日志记录器,代码省略

return logger;

}

public Logger createLogger(String args) {

//使用参数args作为连接字符串来连接数据库,代码省略

Logger logger = new DatabaseLogger();

//初始化数据库日志记录器,代码省略

return logger;

}

public Logger createLogger(Object obj) {

//使用封装在参数obj中的连接字符串来连接数据库,代码省略

Logger logger = new DatabaseLogger();

//使用封装在参数obj中的数据来初始化数据库日志记录器,代码省略

return logger;

}

}

抽象工厂模式

问题:

Sunny软件公司欲开发一套界面皮肤库,可以对Java桌面软件进行界面美化。为了保护版权,该皮肤库源代码不打算公开,而只向用户提供已打包为jar文件的class字节码文件。用户在使用时可以通过菜单来选择皮肤,不同的皮肤将提供视觉效果不同的按钮、文本框、组合框等界面元素,其结构示意图如图1所示:

该皮肤库需要具备良好的灵活性和可扩展性,用户可以自由选择不同的皮肤,开发人员可以在不修改既有代码的基础上增加新的皮肤。

//在本实例中我们对代码进行了大量简化,实际使用时,界面组件的初始化代码较为复杂,还需要使用JDK中一些已有类,为了突出核心代码,在此只提供框架代码和演示输出。

//按钮接口:抽象产品

interface Button {

public void display();

}

//Spring按钮类:具体产品

class SpringButton implements Button {

public void display() {

System.out.println("显示浅绿色按钮。");

}

}

//Summer按钮类:具体产品

class SummerButton implements Button {

public void display() {

System.out.println("显示浅蓝色按钮。");

}

}

//文本框接口:抽象产品

interface TextField {

public void display();

}

//Spring文本框类:具体产品

class SpringTextField implements TextField {

public void display() {

System.out.println("显示绿色边框文本框。");

}

}

//Summer文本框类:具体产品

class SummerTextField implements TextField {

public void display() {

System.out.println("显示蓝色边框文本框。");

}

}

//组合框接口:抽象产品

interface ComboBox {

public void display();

}

//Spring组合框类:具体产品

class SpringComboBox implements ComboBox {

public void display() {

System.out.println("显示绿色边框组合框。");

}

}

//Summer组合框类:具体产品

class SummerComboBox implements ComboBox {

public void display() {

System.out.println("显示蓝色边框组合框。");

}

}

//界面皮肤工厂接口:抽象工厂

interface SkinFactory {

public Button createButton();

public TextField createTextField();

public ComboBox createComboBox();

}

//Spring皮肤工厂:具体工厂

class SpringSkinFactory implements SkinFactory {

public Button createButton() {

return new SpringButton();

}

public TextField createTextField() {

return new SpringTextField();

}

public ComboBox createComboBox() {

return new SpringComboBox();

}

}

//Summer皮肤工厂:具体工厂

class SummerSkinFactory implements SkinFactory {

public Button createButton() {

return new SummerButton();

}

public TextField createTextField() {

return new SummerTextField();

}

public ComboBox createComboBox() {

return new SummerComboBox();

}

}

单例模式:

第一种(懒汉,线程不安全):

1 public class Singleton {

2     private static Singleton instance;

3     private Singleton (){}

4     public static Singleton getInstance() {

5     if (instance == null) {

6         instance = new Singleton();

7     }

8     return instance;

9     }

10 }

第二种 懒汉式单例: 加了线程安全锁,性能下降。

class LazySingleton {

private static LazySingleton instance = null;

private LazySingleton() { }

synchronized public static LazySingleton getInstance() {

if (instance == null) {

instance = new LazySingleton();

}

return instance;

}

}

该懒汉式单例类在getInstance()方法前面增加了关键字synchronized进行线程锁,以处理多个线程同时访问的问题。但是,上述代码虽然解决了线程安全问题,但是每次调用getInstance()时都需要进行线程锁定判断,在多线程高并发访问环境中,将会导致系统性能大大降低。如何既解决线程安全问题又不影响系统性能呢?我们继续对懒汉式单例进行改进。事实上,我们无须对整个getInstance()方法进行锁定,只需对其中的代码“instance
= new LazySingleton();”进行锁定即可。因此getInstance()方法可以进行如下改进:

第三种  (双重校验锁)

class LazySingleton {

private volatile static LazySingleton instance = null;

private LazySingleton() { }

public static LazySingleton getInstance() {

//第一重判断

if (instance == null) {

//锁定代码块

synchronized (LazySingleton.class) {

//第二重判断

if (instance == null) {

instance = new LazySingleton(); //创建单例实例

}

}

}

return instance;

}

}

以下方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

第四种:饿汉式单例:不能实现延迟加载,不管将来用不用始终占据内存

class EagerSingleton {

private static final EagerSingleton instance = new EagerSingleton();

private EagerSingleton() { }

public static EagerSingleton getInstance() {

return instance;

}

}

第五种(饿汉,变种):表面上看起来差别挺大,其实更第四种方式差不多,都是在类初始化即实例化instance。

1 public class Singleton {

2     private Singleton instance = null;

3     static {

4     instance = new Singleton();

5     }

6     private Singleton (){}

7     public static Singleton getInstance() {

8     return this.instance;

9     }

10 }

11

第六种(静态内部类):

class Singleton {

private Singleton() {

}

private static class HolderClass {

private final static Singleton instance = new Singleton();

}

public static Singleton getInstance() {

return HolderClass.instance;

}

public static void main(String args[]) {

Singleton s1, s2;

s1 = Singleton.getInstance();

s2 = Singleton.getInstance();

System.out.println(s1==s2);

}

}

第七种(枚举):

1 public enum Singleton {

2     INSTANCE;

3     public void whateverMethod() {

4     }

5 }

原型模式

问题:

Sunny软件公司一直使用自行开发的一套OA (Office Automatic,办公自动化)系统进行日常工作办理,但在使用过程中,越来越多的人对工作周报的创建和编写模块产生了抱怨。追其原因,Sunny软件公司的OA管理员发现,由于某些岗位每周工作存在重复性,工作周报内容都大同小异,如图7-1工作周报示意图。这些周报只有一些小地方存在差异,但是现行系统每周默认创建的周报都是空白报表,用户只能通过重新输入或不断复制粘贴来填写重复的周报内容,极大降低了工作效率,浪费宝贵的时间。如何快速创建相同或者相似的工作周报,成为Sunny公司OA开发人员面临的一个新问题。

答案:


class WeeklyLog implements Cloneable

{

private  String name;

private  String date;

private  String content;

public  void setName(String name) {

this.name  = name;

}

public  void setDate(String date) {

this.date  = date;

}

public  void setContent(String content) {

this.content  = content;

}

public  String getName() {

return  (this.name);

}

public  String getDate() {

return  (this.date);

}

public  String getContent() {

return  (this.content);

}

//克隆方法clone(),此处使用Java语言提供的克隆机制

       public WeeklyLog clone()

       {

              Object obj = null;

              try

              {

                     obj = super.clone();

                     return (WeeklyLog)obj;     

              }

              catch(CloneNotSupportedException e)

              {

                     System.out.println("不支持复制!");

                     return null;

              }

       }

}

编写如下客户端测试代码:


class Client

{

public  static void main(String args[])

{

WeeklyLog log_previous = new WeeklyLog();  //创建原型对象

log_previous.setName("张无忌");

log_previous.setDate("第12周");

log_previous.setContent("这周工作很忙,每天加班!");

System.out.println("****周报****");

System.out.println("周次:" +  log_previous.getDate());

System.out.println("姓名:" +  log_previous.getName());

System.out.println("内容:" +  log_previous.getContent());

System.out.println("--------------------------------");

WeeklyLog  log_new;

       log_new  = log_previous.clone(); //调用克隆方法创建克隆对象

log_new.setDate("第13周");

System.out.println("****周报****");

System.out.println("周次:" + log_new.getDate());

System.out.println("姓名:" + log_new.getName());

System.out.println("内容:" + log_new.getContent());

}

}

通过引入原型模式,Sunny软件公司OA系统支持工作周报的快速克隆,极大提高了工作周报的编写效率,受到员工的一致好评。但有员工又发现一个问题,有些工作周报带有附件,例如经理助理“小龙女”的周报通常附有本周项目进展报告汇总表、本周客户反馈信息汇总表等,如果使用上述原型模式来复制周报,周报虽然可以复制,但是周报的附件并不能复制,这是由于什么原因导致的呢?如何才能实现周报和附件的同时复制呢?


import  java.io.*;

//附件类

class  Attachment implements Serializable

{

private  String name; //附件名

public  void setName(String name)

{

this.name  = name;

}

public  String getName()

{

return  this.name;

}

public void download()

{

System.out.println("下载附件,文件名为" + name);

}

}

工作周报类WeeklyLog不再使用Java自带的克隆机制,而是通过序列化来从头实现对象的深克隆,我们需要重新编写clone()方法,修改后的代码如下:


import  java.io.*;

//工作周报类

class  WeeklyLog implements Serializable

{

private  Attachment attachment;

private  String name;

private  String date;

private  String content;

public  void setAttachment(Attachment attachment) {

this.attachment  = attachment;

}

public  void setName(String name) {

this.name  = name;

}

public  void setDate(String date) {

this.date  = date;

}

public  void setContent(String content) {

this.content  = content;

}

public  Attachment getAttachment(){

return  (this.attachment);

}

public  String getName() {

return  (this.name);

}

public  String getDate() {

return  (this.date);

}

public  String getContent() {

return  (this.content);

}

//使用序列化技术实现深克隆

       public WeeklyLog deepClone() throws  IOException, ClassNotFoundException, OptionalDataException

       {

              //将对象写入流中

              ByteArrayOutputStream bao=new  ByteArrayOutputStream();

              ObjectOutputStream oos=new  ObjectOutputStream(bao);

              oos.writeObject(this);

             

              //将对象从流中取出

              ByteArrayInputStream bis=new  ByteArrayInputStream(bao.toByteArray());

              ObjectInputStream ois=new  ObjectInputStream(bis);

              return  (WeeklyLog)ois.readObject();

       }

}

客户端代码如下所示:


class Client

{

public  static void main(String args[])

{

WeeklyLog  log_previous, log_new = null;

log_previous  = new WeeklyLog(); //创建原型对象

Attachment  attachment = new Attachment(); //创建附件对象

log_previous.setAttachment(attachment);  //将附件添加到周报中

              try

              {

                     log_new =  log_previous.deepClone(); //调用深克隆方法创建克隆对象                  

              }

              catch(Exception e)

              {

                     System.err.println("克隆失败!");

              }

//比较周报

System.out.println("周报是否相同? " + (log_previous ==  log_new));

//比较附件

System.out.println("附件是否相同? " +  (log_previous.getAttachment() == log_new.getAttachment()));

}

}

建造者模式

问题: Sunny软件公司游戏开发小组决定开发一款名为《Sunny群侠传》的网络游戏,该游戏采用主流的RPG(Role Playing Game,角色扮演游戏)模式,玩家可以在游戏中扮演虚拟世界中的一个特定角色,角色根据不同的游戏情节和统计数据(如力量、魔法、技能等)具有不同的能力,角色也会随着不断升级而拥有更加强大的能力。

作为RPG游戏的一个重要组成部分,需要对游戏角色进行设计,而且随着该游戏的升级将不断增加新的角色。不同类型的游戏角色,其性别、脸型、服装、发型等外部特性都有所差异,例如“天使”拥有美丽的面容和披肩的长发,并身穿一袭白裙;而“恶魔”极其丑陋,留着光头并穿一件刺眼的黑衣。

Sunny公司决定开发一个小工具来创建游戏角色,可以创建不同类型的角色并可以灵活增加新的角色。


class Actor

{

private  String type; //角色类型

private  String sex; //性别

private  String face; //脸型

private  String costume; //服装

private  String hairstyle; //发型

public  void setType(String type) {

this.type  = type;

}

public  void setSex(String sex) {

this.sex  = sex;

}

public  void setFace(String face) {

this.face  = face;

}

public  void setCostume(String costume) {

this.costume  = costume;

}

public  void setHairstyle(String hairstyle) {

this.hairstyle  = hairstyle;

}

public  String getType() {

return  (this.type);

}

public  String getSex() {

return  (this.sex);

}

public  String getFace() {

return  (this.face);

}

public  String getCostume() {

return  (this.costume);

}

public  String getHairstyle() {

return  (this.hairstyle);

}

}

//角色建造器:抽象建造者

abstract class ActorBuilder

{

protected  Actor actor = new Actor();

public  abstract void buildType();

public  abstract void buildSex();

public  abstract void buildFace();

public  abstract void buildCostume();

public  abstract void buildHairstyle();

    //工厂方法,返回一个完整的游戏角色对象

       public Actor createActor()

       {

              return actor;

       }

}

//英雄角色建造器:具体建造者

class HeroBuilder extends ActorBuilder

{

public  void buildType()

{

actor.setType("英雄");

}

public  void buildSex()

{

actor.setSex("男");

}

public  void buildFace()

{

actor.setFace("英俊");

}

public  void buildCostume()

{

actor.setCostume("盔甲");

}

public  void buildHairstyle()

{

actor.setHairstyle("飘逸");

}

}

//天使角色建造器:具体建造者

class AngelBuilder extends ActorBuilder

{

public  void buildType()

{

actor.setType("天使");

}

public  void buildSex()

{

actor.setSex("女");

}

public  void buildFace()

{

actor.setFace("漂亮");

}

public  void buildCostume()

{

actor.setCostume("白裙");

}

public  void buildHairstyle()

{

actor.setHairstyle("披肩长发");

}

}

//恶魔角色建造器:具体建造者

class DevilBuilder extends ActorBuilder

{

public  void buildType()

{

actor.setType("恶魔");

}

public  void buildSex()

{

actor.setSex("妖");

}

public  void buildFace()

{

actor.setFace("丑陋");

}

public  void buildCostume()

{

actor.setCostume("黑衣");

}

public  void buildHairstyle()

{

actor.setHairstyle("光头");

}

}

指挥者类ActorController定义了construct()方法,该方法拥有一个抽象建造者ActorBuilder类型的参数,在该方法内部实现了游戏角色对象的逐步构建,代码如下所示:


//游戏角色创建控制器:指挥者

class ActorController

{

  //逐步构建复杂产品对象

       public Actor construct(ActorBuilder ab)

       {

              Actor actor;

              ab.buildType();

              ab.buildSex();

              ab.buildFace();

              ab.buildCostume();

              ab.buildHairstyle();

              actor=ab.createActor();

              return actor;

       }

}

时间: 2024-08-05 06:50:36

设计模式 学习 2:的相关文章

设计模式学习总结

本文是对各处设计模式示例的总结概括和简化,主要参考 http://blog.csdn.net/zhangerqing/article/details/8194653 直接看本文估计比较枯燥无聊,因为没图~~??,建议对设计模式有兴趣的先看看上面的博文,或者基础比较好可直接移到最底下看下我的各模式一句话概括总结,有什么意见建议欢迎提出~~~~~~~~~~ 总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式.结构型模式,共七种:适配器模式.装饰

java/android 设计模式学习笔记(14)---外观模式

这篇博客来介绍外观模式(Facade Pattern),外观模式也称为门面模式,它在开发过程中运用频率非常高,尤其是第三方 SDK 基本很大概率都会使用外观模式.通过一个外观类使得整个子系统只有一个统一的高层的接口,这样能够降低用户的使用成本,也对用户屏蔽了很多实现细节.当然,在我们的开发过程中,外观模式也是我们封装 API 的常用手段,例如网络模块.ImageLoader 模块等.其实我们在开发过程中可能已经使用过很多次外观模式,只是没有从理论层面去了解它. 转载请注明出处:http://bl

java/android 设计模式学习笔记(10)---建造者模式

这篇博客我们来介绍一下建造者模式(Builder Pattern),建造者模式又被称为生成器模式,是创造性模式之一,与工厂方法模式和抽象工厂模式不同,后两者的目的是为了实现多态性,而 Builder 模式的目的则是为了将对象的构建与展示分离.Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程.一个复杂的对象有大量的组成部分,比如汽车它有车轮.方向盘.发动机.以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过

java/android 设计模式学习笔记(一)---单例模式

前段时间公司一些同事在讨论单例模式(我是最渣的一个,都插不上嘴 T__T ),这个模式使用的频率很高,也可能是很多人最熟悉的设计模式,当然单例模式也算是最简单的设计模式之一吧,简单归简单,但是在实际使用的时候也会有一些坑. PS:对技术感兴趣的同鞋加群544645972一起交流 设计模式总目录 java/android 设计模式学习笔记目录 特点 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 单例模式的使用很广泛,比如:线程池(threadpool).缓存(cache).对

java/android 设计模式学习笔记(7)---装饰者模式

这篇将会介绍装饰者模式(Decorator Pattern),装饰者模式也称为包装模式(Wrapper Pattern),结构型模式之一,其使用一种对客户端透明的方式来动态的扩展对象的功能,同时它也是继承关系的一种替代方案之一,但比继承更加灵活.在现实生活中也可以看到很多装饰者模式的例子,或者可以大胆的说装饰者模式无处不在,就拿一件东西来说,可以给它披上无数层不一样的外壳,但是这件东西还是这件东西,外壳不过是用来扩展这个东西的功能而已,这就是装饰者模式,装饰者的这个角色也许各不相同但是被装饰的对

设计模式学习难度系数排名

这是yqj2065感觉的每个设计模式学习难度系数. 刘伟(Sunny)先生有一个5分制的学习难度,列在模式名称之后. 有几个模式的评价差别很大,抽象工厂模式和享元模式给4分/5,而单例模式1分/5.冠军是一样的. 学习难度系数: ☆☆☆☆☆ ☆☆☆☆☆ 依赖注入模式 静态工厂模式 2 策略模式 1 ★☆☆☆☆ ☆☆☆☆☆ 工厂方法模式 2 模板方法模式 2 适配器模式    2 责任链模式   3 外观模式 1 ★★☆☆☆ ☆☆☆☆☆ 抽象工厂模式  4 桥接模式  3 迭代器    3 享元模

设计模式学习--Singleton

What Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点. Why Singletion是我比较熟悉的设计模式之一,在平常的开发过程中,也曾几次用到,它主要适用于如下场景: 1.当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时. 2.当这个唯一实例应该是通过子类可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时. 在系统设计中,在涉及系统资源的管理时,往往会被设计成Singletion模式,比如缓存.日志对象.线程池.对话框等等. How 假设如下场

设计模式学习03—抽象工厂模式

1.动机与定义 工厂模式中,一个工厂仅仅能提供一个或一类产品,当产品种类较多,形成产品系列(比方我们要创建跨平台的button,菜单,文本框等等一系列GUI控件: 单纯使用工厂模式会产生大量工厂,并且后期维护也不方便,我们能够从产品中找到规律,假设产品等级相对固定,以后仅仅会新增产品族,那么我们就能够把整个产品族放到一个工厂创建,以后新增其它系统产品族也很方便,例如以下图: 这样的模式就是抽象工厂,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则须要面对多个产品等级结构,一个工厂等级结构能

大话设计模式学习笔记——面向对象基础

前言 好记性不如烂"笔头"系列--大话设计模式学习笔记 目录 面向对象基础 面向对象基础 什么是类与实例 一切事物皆为对象,即所有的东西老师对象,对象就是可以看到.感觉到.听到.触摸到.尝到.或闻到的东西.准确地说,对象是一个自包含的实体,用一组可识别的特性和行为来标识.面向对象编程,英文叫 Object-Oriented Programming,其实就是针对对象来进行编程的意思.类就是具有相同属性和功能的对象的抽象集合.实例就是一个真实的对象.比如我们属于'人'类,而个人就是'人'类

java/android 设计模式学习笔记(13)---享元模式

这篇我们来介绍一下享元模式(Flyweight Pattern),Flyweight 代表轻量级的意思,享元模式是对象池的一种实现.享元模式用来尽可能减少内存使用量,它适合用于可能存在大量重复对象的场景,缓存可共享的对象,来达到对象共享和避免创建过多对象的效果,这样一来就可以提升性能,避免内存移除和频繁 GC 等. 享元模式的一个经典使用案例是文本系统中图形显示所用的数据结构,一个文本系统能够显示的字符种类就是那么几十上百个,那么就定义这么些基础字符对象,存储每个字符的显示外形和其他的格式化数据