Day322.设计模式回顾 -Java设计模式
Posted 阿昌喜欢吃黄桃
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day322.设计模式回顾 -Java设计模式相关的知识,希望对你有一定的参考价值。
设计模式
一、七大原则
1、单一职责原则
- 一个类就管一件事
2、接口隔离原则
- 一个接口,有他自己的方法;当他的子类实现只需要实现对应只想实现的方法,不应该是全部实现;
- 将
接口Interface1拆分为独立的几个接口
,让一个类对另一个类的依赖应该建立在最小的接口
上
3、依赖倒转原则
- 抽象不应该依赖细节,细节应该依赖抽象
如让一个方法的参数依赖接口,而不是具体的实现类,这样子就可以传入这个接口的实现类,更具有扩展性
4、里氏替换原则
- 子类中尽量
不要重写父类
的方法,可以通过聚合,组合,依赖 来解决问题
5、开闭原则
-
模块和函数应该
对扩展开放
(对提供方),对修改关闭
(对使用方) -
当软件需要变化时,尽量
通过扩展
软件实体的行为来实现变化,而不是通过
修改已有的代码来实现变化。
6、迪米特原则
-
最少知道原则,一个类对自己依赖的类知道的越少越好
-
耦合的方式很多,依赖,关联,组合,聚合等。
其中,我们称出现成员变量,方法参数,方法返回值中的类为 直接的朋友,
而出现在局部变量中的类 不是直接的朋友。
也就是说,陌生的类 最好不要以局部变量的形式出现在类的内部。
7、合成复用原则
尽量使用合成/聚合的方式,而不是使用继承
二、单例模式
采取一定的方法保证在整个的软件系统
中,对某个类只能存在一个对象实例
, 并且该类只提供一个
取得其对象实例的方法
(静态方法)。
1、饿汉式(静态常量)
-
构造器私有化 (防止 new )
-
类的内部创建对象
-
向外暴露一个静态的公共方法。getInstance
public class Singleton1{
private Singleton1(){};
private final static Singleton1 instance = new instance();
public static getInstance(){
return instance;
}
}
优点:
写法简单
,就是在类装载的时候就完成实例化。避免了线程同步问题
。
缺点:
-
内存浪费
-
无lazy loading 的效果
2、饿汉式(静态代码块)
//饿汉式(静态代码块)
public class Singleton2 {
private Singleton2(){}
private final static Singleton2 instance;
static{
instance = new Singleton2();
}
public static Singleton2 getInstance(){
return instance;
}
}
优缺点和上面是一样的。
3、懒汉式(线程不安全)
//懒汉式(线程不安全)
public class Singleton3{
private Singleton3(){};
private Singleton3 instance;
public Singleton3 getInstance(){
if(instance==null){
instance = new Singleton3();
}
return instance;
}
}
优点:
- Lazy Loading 的效果,但是
只能在单线程下使用
。
缺点:
线程不安全
4、懒汉式(线程安全,同步代码块)
//懒汉式(线程安全,同步代码块)
public class Singleton4 {
private Singleton4() {
}
private static Singleton4 instance;
public static Singleton4 getInstance() {
if (instance == null) {
synchronized (this) {
instance = new Singleton4();
}
}
return instance;
}
}
不推荐使用,性能差
5、懒汉式(线程安全,同步方法)
//懒汉式(线程安全,同步方法)
public class Singleton5 {
private Singleton5() { }
private static Singleton5 instance;
public static synchronized Singleton5 getInstance() {
if (instance == null) {
instance = new Singleton5();
}
return instance;
}
}
不推荐使用,性能差
6、双重检查
//双重检查
public class Singleton6 {
private Singleton6() {
}
private static volatile Singleton6 instance;
public Singleton6 getInstance() {
if (instance == null) {
synchronized (this) {
if (instance == null) {
instance = new Singleton6();
}
}
}
return instance;
}
}
线程安全,延迟加载
,效率较高
7、静态内部类
//静态内部类
public class Singleton7 {
private Singleton7(){}
private static class SingletonInstance{
private static final Singleton7 INSTANCE = new Singleton7();
}
public Singleton7 getInstance(){
return SingletonInstance.INSTANCE;
}
}
优点:
- 避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
8、枚举
//枚举类
public enum Singleton8 {
INSTANCE;
}
推荐使用
三、工厂模式
1、简单(静态)工厂模式
- 定义了一个
创建对象的类
,由这个类来封装实例化对象的行为
使用场景:
当我们会用到大量
的创建某种、某类或者某批对象 时,就会使用到工厂模式.
2、工厂方法模式
定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类
。
3、抽象工厂模式
-
定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类
-
可以将
简单工厂模式
和工厂方法模式
进行整合
。 -
将工厂抽象成两层,AbsFactory(*抽象工厂*) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了
工厂簇
,更利于代码的维护和扩展。
创建对象实例时,不要直接 new 类, 而是把这个 new 类的动作放在一个工厂的方法中,并返回。有的书上说, 变量不要直接持有具体类的引用
四、原型模式
孙大圣拔出猴毛, 变出其它孙大圣
- 用原型实例指定创建对象的种类,并且通过
拷贝克隆
这些原型,创建新的对象
代码演示:
五、建造者模式
抽象建造的过程
,让具体的实现类去实现各自的建造过程
- Product(产品角色):
一个具体的产品对象。
- Builder(抽象建造者):
创建一个 Product 对象的各个部件指定的 接口**/**抽象类。
- ConcreteBuilder(具体建造者):
实现接口,构建和装配各个部件。
- Director(指挥者):
构建一个使用 Builder 接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
六、适配器模式
- 将一个类的接口转换成另一种接口.
让原本接口不兼容的类可以兼容
- 类适配器模式
通过类继承
- 对象适配器模式
通过成员变量聚合关系实现
- 接口适配器模式
通过一个中间抽象类来空实现,然后子类之间继承中间抽象类,对自己需要实现的方法实现
- 类适配器:以类给到,在 Adapter 里,就是将 src 当做类,
继承
- 对象适配器:以对象给到,在 Adapter 里,将 src 作为一个对象,
持有(组合、聚合)
- 接口适配器:以接口给到,在 Adapter 里,将 src 作为一个接口,
实现
七、桥接模式
- 将
实现与抽象放在两个不同的类层次中
,使两个层次可以独立改变。
//品牌接口
public interface Brand {
void open();
void close();
void call();
}
桥接类聚合了品牌接口类,然后在构造器中传入具体的品牌实现类,在具体的方法做品牌里面的方法调用
实现了抽象和实现部分的分离,从而极大的提供了系统的灵活性,让抽象部分和实现部分独立开来,这有助于系统进行分层设计,从而产生更好的结构化系统
八、装饰者模式
-
套娃模式,直接new放构造器里面套把抽象类聚合到它的子类里 该子类(装饰者)构造抽象类的实现(被装饰者)
-
动态的
将新功能附加到对象上
。在对象功能扩展方面,它比继承更有弹性
,装饰者模式也体现了开闭原则**(ocp**)
代码实现:
九、组合模式
- 它创建了对象组的树形结构,将对象组合成树状结构以表示
“整体-部分”的层次关系
- 通过
组织结构管理
,下面的例子采用了 集合管理
代码实现:
public abstract class OrganizationComponent {
private String name; // 名 字
private String des; // 说 明
protected void add(OrganizationComponent organizationComponent) {
//默认实现
throw new UnsupportedOperationException();
}
protected void remove(OrganizationComponent organizationComponent) {
//默认实现
throw new UnsupportedOperationException();
}
//构造器
public OrganizationComponent(String name, String des) {
super();
this.name = name; this.des = des;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
//方法 print, 做成抽象的, 子类都需要实现
protected abstract void print();
}
public class Client {
public static void main(String[] args) {
//从大到小创建对象 学校
OrganizationComponent university = new University("清华大学", " 中国顶级大学 ");
//创建 学院
OrganizationComponent computerCollege = new College(" 计 算 机 学 院 ", " 计 算 机 学 院 "); OrganizationComponent infoEngineercollege = new College("信息工程学院", " 信息工程学院 ");
//创建各个学院下面的系(专业)
computerCollege.add(new Department("软件工程", " 软件工程不错 "));
computerCollege.add(new Department("网络工程", " 网络工程不错 "));
computerCollege.add(new Department("计算机科学与技术", " 计算机科学与技术是老牌的专业 "));
infoEngineercollege.add(new Department("通信工程", " 通信工程不好学 "));
infoEngineercollege.add(new Department("信息工程", " 信息工程好学 "));
//将学院加入到 学校
university.add(computerCollege);
university.add(infoEngineercollege);
//university.print();
infoEngineercollege.print();
}
}
需要遍历组织机构,或者处理的对象具有树形结构时, 非常适合使用组合模式.
要求较高的抽象性,
如果节点和叶子有很多差异性的话,比如很多方法和属性都不一样,不适合使用组合模式
十、外观模式
-
外观类就是
总控开关
,去管理聚合的所有类 -
解决多个复杂接口带来的使用困难,起到简化用户操作的作用
代码:
- 外观类
集合了需要使用的类,和方法,用户只需要调用这个类的某个方法即可
public class HomeTheaterFacade {
//定义各个子系统对象,聚合关系
private TheaterLight theaterLight;
private Popcorn popcorn;
private Stereo stereo;
private Projector projector;
private Screen screen;
private DVDPlayer dVDPlayer;
//构造器
public HomeTheaterFacade() {
super();
this.theaterLight = TheaterLight.getInstance();
this.popcorn = Popcorn.getInstance();
this.stereo = Stereo.getInstance();
this.projector = Projector.getInstance();
this.screen = Screen.getInstance();
this.dVDPlayer = DVDPlayer.getInstanc();
}
//操作分成 4 步
public void ready() {
popcorn.on();
popcorn.pop();
screen.down();
projector.on();
stereo.on();
dVDPlayer.on();
theaterLight.dim();
}
public void play() {
dVDPlayer.play();
}
public void pause() {
dVDPlayer.pause();
}
public void end() {
popcorn.off();
theaterLight.bright();
screen.up();
projector.off();
stereo.off();
dVDPlayer.off();
}
}
外观模式
对外屏蔽了子系统的细节
,因此外观模式降低了客户端对子系统使用的复杂性
在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade 类,来提供遗留系统的比较清晰简单的接口,让新系统与 Facade 类交互,
提高复用性
十一、享元模式
-
需要的
网站结构相似度很高
,而且都不是高访问量网站,如果分成多个虚拟空间来处理,相当于一个相同网站的实例对象很多,造成服务器的资源浪费
-
运用
共享技术
有效地支持大量细粒度的对象 -
避免重新创建,如果没有我们需要的,则创建一个
内部状态 指 :对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变
外部状态 指 :对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态
。
代码:
// 网站工厂类,根据需要返回压一个网站
public class WebSiteFactory {
//集合, 充当池的作用
private HashMap<String, ConcreteWebSite> pool = new HashMap<>();
//根据网站的类型,返回一个网站, 如果没有就创建一个网站,并放入到池中,并返回
public WebSite getWebSiteCategory(String type) {
if(!pool.containsKey(type)) {
//就创建一个网站,并放入到池中
pool.put(type, new ConcreteWebSite(type));
}
return (WebSite)pool.get(type);
}
//获取网站分类的总数 (池中有多少个网站类型)
public int getWebSiteCount() {
return pool.size();
}
}
public class Client {
public static void main(String[] args) {
// 创建一个工厂类
WebSiteFactory factory = new WebSiteFactory();
// 客户要一个以新闻形式发布的网站
WebSite webSite1 = factory.getWebSiteCategory("新闻");
webSite1.use(new User("tom"));
// 客户要一个以博客形式发布的网站
WebSite webSite2 = factory.getWebSiteCategory("博客");
webSite2.use(new User("jack"));
// 客户要一个以博客形式发布的网站
WebSite webSite3 = factory.getWebSiteCategory("博客");
webSite3.use(new User("smith"));
// 客户要一个以博客形式发布的网站
WebSite webSite4 = factory.getWebSiteCategory("博客");
webSite4.use(new User("阿昌"));
System.out.println("网站的分类共=" + factory.getWebSiteCount());
}
}
//具体网站
public class ConcreteWebSite extends WebSite {
//共享的部分,内部状态
private String type = ""; //网站发布的形式(类型)
//构造器
public ConcreteWebSite(String type) {
this.type = type;
}
@Override
public void use(User user) {
System.out.println("网站的发布形式为:" + type + " 在使用中 .. 使用者是" + user.getName());
}
}
@Data
public class User {
private String name;
public User(String name) {
super();
this.name = name;
}
}
public abstract class WebSite {
public abstract void use(User user);//抽象方法
}
享元模式
大大减少了对象的创建,降低了程序内存的占用,提高效率
享元模式提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变,这是我们使用享元模式需要注意的地方.
使用享元模式时,注意划分
内部状态和外部状态
,并且需要有一个工厂类加以控制。
明天继续
以上是关于Day322.设计模式回顾 -Java设计模式的主要内容,如果未能解决你的问题,请参考以下文章