设计模式基本认知
1设计模式的六大原则
1)开闭原则
对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能修改原有的代码,要实现热插拔的效果。为了使程序的扩展性好,易于维护和升级,我们需要使用接口的抽象类。
2)里氏代换原则
是面向对象设计的基本原则之一。 里氏代换原则说任何基类出现的地方,子类一定可以出现。只有当衍生类可以替换调基类,软件单位的功能不收到影响时,基类才能被真正复用,而衍生类也可以在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
3)依赖倒转原则
是 “开-闭”原则的基础,针对接口编程,依赖于抽象而不是具体的实现类。
4)接口隔离原则
使用多个隔离的接口比使用单个接口好,降低类之间的耦合度。
5)迪米特法则(最少知道原则)
一个实体应当尽量少的和其他实体相互作用,使系统功能模块相对独立。
6)合成复用原则
尽量使用合成/聚合方式,而不是继承。
2.设计模式三大类
1)创建模型(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。
2)结构型模式(7种):适配器模式,装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
3)行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
3.设计模式
1)单例模式(Singleton)
某个类只能生成一个实例,该类提供一个全局访问点供外部获取该实例,其拓展是有很多例模式。
优点:只有一个实例,节约了内存资源,提高了系统性能。
缺点:没有抽象层,不能扩展。职责过重,违背了单一性原则。
简单的懒汉式单例,但是线程不安全,在并发环境下可能出现多个实例。
//懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton {
private Singleton() {}
private static Singleton single=null;
//静态工厂方法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
比较好的安全的懒汉式
双重检查锁定方式
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
静态内部类方式
public class Singleton {
private Singleton() {
}
private static class SingletonFactory{
private static final Singleton instance=new Singleton();
}
public static final Singleton getInstance(){
return SingletonFactory.instance;
}
}
饿汉式单例
//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton{
private Singleton() {}
private static final Singleton single = new Singleton();
//静态工厂方法
public static Singleton getInstance() {
return single;
}
}
2)工厂方法模式
一般采用静态工厂模式,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。
优点:客户端不需要创建对象,明确了各个类的职责
缺点:该工厂类负责创建所有实例,如果有新的类加入,需要不断的修改工厂类,不利于后期的维护
创建共同接口
public interface Sender {
public void Send();
}
创建实现类
public class MailSender implements Sender {
@Override
public void Send() {
System.out.println("this is mailsender!");
}
public class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("this is sms sender!");
}
}
创建静态工厂类
public class SendFactory {
public static Sender produceMail(){
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
测试
public class FactoryTest {
public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.Send();
}
}
3)抽象工厂模式
工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则。所以我们要用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
好处:如果有新的类进来,只需要添加一个对应的具体工厂类,不影响现有代码,增加了程序的扩展性。
缺点:增加了代码量
创建共同接口。
public interface Sender {
public void Send();
}
创建实现类
public class MailSender implements Sender {
@Override
public void Send() {
System.out.println("this is mailsender!");
}
public class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("this is sms sender!");
}
}
再提供一个接口
public interface Provider {
public Sender produce();
}
两个工厂类
public class SendMailFactory implements Provider {
@Override
public Sender produce(){
return new MailSender();
}
}
public class SendSmsFactory implements Provider{
@Override
public Sender produce() {
return new SmsSender();
}
}
测试
public class Test {
public static void main(String[] args) {
Provider provider = new SendMailFactory();
Sender sender = provider.produce();
sender.Send();
}
}
4)建造者模式
工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性。
创建共同接口
public interface Sender {
public void Send();
}
创建实现类
public class MailSender implements Sender {
@Override
public void Send() {
System.out.println("this is mailsender!");
}
public class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("this is sms sender!");
}
}
建造者类
public class Builder {
private List<Sender> list = new ArrayList<Sender>();
public void produceMailSender(int count){
for(int i=0; i<count; i++){
list.add(new MailSender());
}
}
public void produceSmsSender(int count){
for(int i=0; i<count; i++){
list.add(new SmsSender());
}
}
}
测试
public class Test {
public static void main(String[] args) {
Builder builder = new Builder();
builder.produceMailSender(10);
}
}
5)适配器模式
适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。
类的适配器:核心思想就是:有一个被继承的父类,拥有一个方法,待适配,有一个被实现的接口,通过一个类继承父类并实现接口,把父类的方法扩展到接口中。
父类
public class Source {
public void methodClass(){
System.out.println("类中的方法");
}
}
接口
interface Targetable{
//与类中的方法一致
public void methodClass();
//接口的方法
public void methodIt();
}
写一个类继承父类并实现接口
class Adapter extends Source implements Targetable{
@Override
public void methodIt() {
System.out.println("接口中的方法");
}
}
测试
class test{
public static void main(String[] args) {
Targetable targetable = new Adapter();
targetable.methodIt();
targetable.methodClass();
}
}
对象的适配器:基本思路和类的适配器模式相同,我们写的类不继承方法对象类,而是持有那个类的实例,已达到兼容性的问题。
方法对象类
public class Source {
public void methodClass(){
System.out.println("类中的方法");
}
}
接口
interface Targetable{
//与类中的方法一致
public void methodClass();
//接口的方法
public void methodIt();
}
写一个类持有方法对象类的实例并实现接口
class Adapter implements Targetable{
private Source source;
public Adapter(Source source) {
this.source = source;
}
@Override
public void methodClass() {
source.methodClass();
}
@Override
public void methodIt() {
System.out.println("接口中的方法");
}
}
测试
class test{
public static void main(String[] args) {
Source source = new Source();
Targetable targetable = new Adapter(source);
targetable.methodIt();
targetable.methodClass();
}
}
接口的适配器:写一个抽象类继承接口的所有方法,之后在写类继承抽象类,获取我们所需要的方法,而不是把接口中的所有方法都进行复写。
接口
interface Targetable{
public void methodClass();
public void methodIt();
}
抽象类
abstract class Adapter implements Targetable{
@Override
public void methodClass() {
System.out.println("抽象类方法");
}
@Override
public void methodIt() {
System.out.println("抽象类方法");
}
}
继承类一
class demo1 extends Adapter{
@Override
public void methodClass() {
System.out.println("demo1");
}
}
继承类二
class demo2 extends Adapter{
@Override
public void methodIt() {
System.out.println("demo2");
}
}
测试
class test{
public static void main(String[] args) {
Adapter demo1 = new demo1();
Adapter demo2 = new demo2();
demo1.methodClass();
demo1.methodIt();
demo2.methodClass();
demo2.methodIt();
}
}
总结三种适配器模式的应用场景:
类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。
对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。
接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。
6)装饰模式
给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。
接口
interface Targetable{
public void methodIt();
}
被装饰类
class Decorated implements Targetable{
@Override
public void methodIt() {
System.out.println("被装饰者");
}
}
装饰类
class Decorater implements Targetable{
private Targetable targetable;
public Decorater(Targetable targetable) {
this.targetable = targetable;
}
@Override
public void methodIt() {
System.out.println("装饰一下在前面");
targetable.methodIt();
System.out.println("装饰一下在后面");
}
}
测试
class test{
public static void main(String[] args) {
Targetable targetable = new Decorated();
Targetable decorater = new Decorater(targetable);
decorater.methodIt();
}
}
7)代理模式
为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
接口
interface Targetable{
public void methodIt();
}
被代理类
class Decorated implements Targetable{
@Override
public void methodIt() {
System.out.println("被代理者");
}
}
代理类
class Decorater implements Targetable {
private Targetable targetable;
public Decorater(Targetable targetable) {
this.targetable = targetable;
}
@Override
public void methodIt() {
before();
targetable.methodIt();
after();
}
public void before() {
System.out.println("代理对象执行之前");
}
public void after() {
System.out.println("代理对象执行之后");
}
}
测试
class test{
public static void main(String[] args) {
Targetable targetable = new Decorated();
Targetable decorater = new Decorater(targetable);
decorater.methodIt();
}
}
8)观察者模式
多个对象间存在一对多关系,当一个对象发生改变时,会把这种改变通知给其他多个对象,从而影响其他对象的行为。
接口
interface Targetable {
public void methodIt();
}
实现类一
class demo1 implements Targetable {
@Override
public void methodIt() {
System.out.println("实现类一");
}
}
实现类二
class demo2 implements Targetable {
@Override
public void methodIt() {
System.out.println("实现类二");
}
}
监控接口
interface Subject{
public void add(Targetable targetable);
public void delete(Targetable targetable);
public void notifyDemo();
public void operation();
}
监控接口实现类
abstract class AbstractSubject implements Subject{
private Vector<Targetable> vector=new Vector<Targetable>();
@Override
public void add(Targetable targetable) {
vector.add(targetable);
}
@Override
public void delete(Targetable targetable) {
vector.remove(targetable);
}
@Override
public void notifyDemo() {
Enumeration<Targetable> elements = vector.elements();
while (elements.hasMoreElements()){
elements.nextElement().methodIt();
}
}
}
主对象
class MySubject extends AbstractSubject{
@Override
public void operation() {
System.out.println("基本方法");
notifyDemo();
}
}
测试
class test {
public static void main(String[] args) {
MySubject mySubject = new MySubject();
mySubject.add(new demo1());
mySubject.add(new demo2());
mySubject.operation();
}
}
整理借鉴了很多大佬写的,绝大部分借鉴于此大佬(http://blog.csdn.net/zhangerqing),其他在此无法一一说明,这只是个人用来查漏补缺的文章,如果对你有帮助我很高兴。