赞
踩
参考答案
单一职责原则
一个类,应当只有一个引起它变化的原因;即一个类应该只有一个职责。
就一个类而言,应该只专注于做一件事和仅有一个引起变化的原因,这就是所谓的单一职责原则。该原则提出了对对象职责的一种理想期望,对象不应该承担太多职责,正如人不应该一心分为二用。唯有专注,才能保证对象的高内聚;唯有单一,才能保证对象的细粒度。对象的高内聚与细粒度有利于对象的重用。一个庞大的对象承担了太多的职责,当客户端需要该对象的某一个职责时,就不得不将所有的职责都包含进来,从而造成冗余代码。
里氏替换原则
在面向对象的语言中,继承是必不可少的、优秀的语言机制,它主要有以下几个优点:
相应的,继承也存在缺点,主要体现在以下几个方面:
从整体上看,继承的“利”大于“弊”,然而如何让继承中“利”的因素发挥最大作用,同时减少“弊”所带来的麻烦,这就需要引入“里氏替换原则”。里氏替换原则的定义有以下两种:
依赖倒置原则
依赖倒置原则包括三种含义:
传统的过程性系统的设计办法倾向于高层次的模块依赖于低层次的模块;抽象层次依赖于具体层次。“倒置”原则将这个错误的依赖关系倒置了过来,如下图所示,由此命名为“依赖倒置原则”。
在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是具体的实现类,实现类实现了接口或继承了抽象类,其特点是可以直接被实例化。依赖倒置原则在Java语言中的表现是:
依赖倒置原则更加精确的定义就是“面向接口编程”——OOD(Object-Oriented Design)的精髓之一。依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。依赖倒置原则是JavaBean、EJB和COM等组件设计模型背后的基本原则。
接口隔离原则
接口隔离原则有如下两种定义:
接口隔离原则的具体含义如下:
迪米特法则
迪米特法则又叫最少知识原则,意思是一个对象应当对其他对象尽可能少的了解。迪米特法则不同于其他的OO设计原则,它具有很多种表述方式,其中具有代表性的是以下几种表述:
按照迪米特法则,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用;如果一个类需要调用另一个类的某一个方法,可以通过第三者转发这个调用。
开闭原则的定义是:一个软件实体应当对扩展开放,对修改关闭。这个原则说的是,在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,即应当可以在不必修改源代码的情况下改变这个模块的行为。
在面向对象的编程中,开闭原则是最基础的原则,起到总的指导作用,其他原则(单一职责、里氏替换、依赖倒置、接口隔离、迪米特法则)都是开闭原则的具体形态,即其他原则都是开闭原则的手段和工具。开闭原则的重要性可以通过以下几个方面来体现。
参考答案
开闭原则的定义是:一个软件实体应当对扩展开放,对修改关闭。这个原则说的是,在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,即应当可以在不必修改源代码的情况下改变这个模块的行为。
在面向对象的编程中,开闭原则是最基础的原则,起到总的指导作用,其他原则(单一职责、里氏替换、依赖倒置、接口隔离、迪米特法则)都是开闭原则的具体形态,即其他原则都是开闭原则的手段和工具。开闭原则的重要性可以通过以下几个方面来体现。
参考答案
饿汉式单例模式:
public class Singleton {
private static Singleton instance = new Singleton();
// 私有构造方法,保证外界无法直接实例化。
private Singleton() {}
// 通过公有的静态方法获取对象实例
public static Singleton getInstace() {
return instance;
}
}
懒汉式单例模式:
public class Singleton {
private static Singleton instance = null;
// 私有构造方法,保证外界无法直接实例化。
private Singleton() {}
// 通过公有的静态方法获取对象实例
public static Singleton getInstace() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
参考答案
在懒汉式单例模式基础上实现线程同步:
public class Singleton {
private static Singleton instance = null;
// 私有构造方法,保证外界无法直接实例化。
private Singleton() {}
// 通过公有的静态方法获取对象实例
synchronized public static Singleton getInstace() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
上述代码对静态方法 getInstance()进行同步,以确保多线程环境下只创建一个实例。如果getInstance()方法未被同步,并且线程A和线程B同时调用此方法,则执行if (instance == null)
语句时都为真,那么线程A和线程B都会创建一个对象,在内存中就会出现两个对象,这样就违反了单例模式。而使用synchronized关键字进行同步后,则不会出现此种情况。
参考答案
工厂模式的用意是定义一个创建产品对象的工厂接口,将实际创建性工作推迟到子类中。工厂模式可分为简单工厂、工厂方法和抽象工厂模式。注意,我们常说的23种经典设计模式,包含了工程方法模式和抽象工厂模式,而并未包含简单工厂模式。另外,我们平时说的工厂模式,一般默认是指工厂方法模式。
简单工厂
简单工厂模式其实并不算是一种设计模式,更多的时候是一种编程习惯。简单工厂的实现思路是,定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。简单工厂的适用场景是:
示例:
创建一个可以绘制不同形状的绘图工具,可以绘制圆形,正方形,三角形,每个图形都会有一个draw()方法用于绘图,不看代码先考虑一下如何通过该模式设计完成此功能。
由题可知圆形,正方形,三角形都属于一种图形,并且都具有draw方法,所以首先可以定义一个接口或者抽象类,作为这三个图像的公共父类,并在其中声明一个公共的draw方法:
public interface Shape {
void draw();
}
下面就是编写具体的图形,每种图形都实现Shape接口:
// 圆形 class CircleShape implements Shape { public CircleShape() { System.out.println("CircleShape: created"); } @Override public void draw() { System.out.println("draw: CircleShape"); } } // 正方形 class RectShape implements Shape { public RectShape() { System.out.println("RectShape: created"); } @Override public void draw() { System.out.println("draw: RectShape"); } } // 三角形 public class TriangleShape implements Shape { public TriangleShape() { System.out.println("TriangleShape: created"); } @Override public void draw() { System.out.println("draw: TriangleShape"); } }
下面是工厂类的具体实现:
class ShapeFactory {
public static Shape getShape(String type) {
Shape shape = null;
if (type.equalsIgnoreCase("circle")) {
shape = new CircleShape();
} else if (type.equalsIgnoreCase("rect")) {
shape = new RectShape();
} else if (type.equalsIgnoreCase("triangle")) {
shape = new TriangleShape();
}
return shape;
}
}
为工厂类传入不同的type可以new不同的形状,返回结果为Shape 类型,这个就是简单工厂核心的地方了。
工厂方法
工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。
工厂方法的实现思路是,定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
示例:
现在需要设计一个这样的图片加载类,它具有多个图片加载器,用来加载jpg,png,gif格式的图片,每个加载器都有一个read()方法,用于读取图片。下面我们完成这个图片加载类。
首先完成图片加载器的设计,编写一个加载器的公共接口:
public interface Reader {
void read();
}
然后完成各个图片加载器的代码:
// jpg图片加载器 class JpgReader implements Reader { @Override public void read() { System.out.print("read jpg"); } } // png图片加载器 class PngReader implements Reader { @Override public void read() { System.out.print("read png"); } } // gif图片加载器 class GifReader implements Reader { @Override public void read() { System.out.print("read gif"); } }
现在我们按照定义所说定义一个抽象的工厂接口ReaderFactory:
interface ReaderFactory {
Reader getReader();
}
里面有一个getReader()方法返回我们的Reader 类,接下来我们把上面定义好的每个图片加载器都提供一个工厂类,这些工厂类实现了ReaderFactory 。
// jpg加载器工厂 class JpgReaderFactory implements ReaderFactory { @Override public Reader getReader() { return new JpgReader(); } } // png加载器工厂 class PngReaderFactory implements ReaderFactory { @Override public Reader getReader() { return new PngReader(); } } // gif加载器工厂 class GifReaderFactory implements ReaderFactory { @Override public Reader getReader() { return new GifReader(); } }
在每个工厂类中我们都通过重写的getReader()方法返回各自的图片加载器对象。
和简单工厂对比一下,最根本的区别在于,简单工厂只有一个统一的工厂类,而工厂方法是针对每个要创建的对象都会提供一个工厂类,这些工厂类都实现了一个工厂基类。
下面总结一下工厂方法的适用场景:
抽象工厂
这个模式最不好理解,而且在实际应用中局限性也蛮大的,因为这个模式并不符合开闭原则。实际开发还需要做好权衡。抽象工厂模式是工厂方法的仅一步深化,在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象。这是和工厂方法最大的不同点。
抽象工厂的实现思路是,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂和工厂方法一样可以划分为4大部分:
示例:
现在需要做一款跨平台的游戏,需要兼容Android,Ios,Wp三个移动操作系统,该游戏针对每个系统都设计了一套操作控制器(OperationController)和界面控制器(UIController),下面通过抽闲工厂方式完成这款游戏的架构设计。
由题可知,游戏里边的各个平台的UIController和OperationController应该是我们最终生产的具体产品。所以新建两个抽象产品接口。
抽象操作控制器:
interface OperationController {
void control();
}
抽象界面控制器:
interface UIController {
void display();
}
然后完成各个系统平台的具体操作控制器和界面控制器。
Android:
class AndroidOperationController implements OperationController {
@Override
public void control() {
System.out.println("AndroidOperationController");
}
}
class AndroidUIController implements UIController {
@Override
public void display() {
System.out.println("AndroidInterfaceController");
}
}
IOS:
class
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。